<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>视频流叠加（AR+AI demo）</title>
    <base href="/static/">
    <!-- 视频播放库 -->
    <script src="js/hls.min.js"></script>
    <script src="js/flv.min.js"></script>
    <script src="js/video.min.js"></script>
    <link href="js/video-js.css" rel="stylesheet">
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        
        body {
            font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
            margin: 0;
            background: linear-gradient(135deg, #1e1e2e 0%, #313244 50%, #45475a 100%);
            color: #cdd6f4;
            min-height: 100vh;
            padding: 15px;
            display: flex;
            flex-direction: column;
            align-items: center;
        }
        
        .container {
            
            width: 100%;
            background: rgba(30, 30, 46, 0.95);
            border-radius: 16px;
            padding: 20px;
            box-shadow: 
                0 15px 35px rgba(0, 0, 0, 0.4),
                0 0 0 1px rgba(137, 220, 235, 0.1);
            margin-top: 10px;
            backdrop-filter: blur(10px);
            border: 1px solid rgba(255, 255, 255, 0.1);
        }
        
        h1 {
            text-align: center;
            margin-bottom: 15px;
            font-size: 2rem;
            background: linear-gradient(to right, #89dceb, #cba6f7);
            -webkit-background-clip: text;
            background-clip: text;
            color: transparent;
        }
        
        .video-container {
            position: relative;
            width: 100%;
            background: #000;
            border-radius: 12px;
            overflow: hidden;
            box-shadow: 
                0 12px 30px rgba(0, 0, 0, 0.6),
                0 0 0 1px rgba(137, 220, 235, 0.2);
            border: 2px solid rgba(137, 220, 235, 0.1);
        }
        
        #videoCanvas {
            width: 100%;
            display: block;
        }
        
        .main-content {
            display: flex;
            gap: 20px;
            align-items: flex-start;
        }
        
        .left-panel {
            flex: 1;
            min-width: 1000px;
            display: flex;
            flex-direction: column;
            gap: 15px;
        }
        
        .right-panel {
            width: 420px;
            flex-shrink: 0;
            padding: 15px;
            background: rgba(49, 50, 68, 0.8);
            border-radius: 12px;
            box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3);
        }
        
        .controls {
            padding: 20px;
            background: rgba(49, 50, 68, 0.8);
            border-radius: 12px;
            box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3);
        }
        
        .control-row {
            display: flex;
            flex-direction: column;
            gap: 18px;
        }
        
        .control-section {
            background: rgba(30, 30, 46, 0.6);
            padding: 20px;
            border-radius: 10px;
            border: 1px solid rgba(137, 220, 235, 0.2);
        }
        
        .control-section h3 {
            margin-bottom: 18px;
            color: #89dceb;
            font-size: 1rem;
            font-weight: 600;
            display: flex;
            align-items: center;
            gap: 6px;
        }
        
        .button-group {
            display: grid;
            grid-template-columns: 1fr 1fr auto;
            gap: 15px;
            margin-bottom: 20px;
            align-items: center;
        }
        
        .button-group .btn {
            width: 100%;
            justify-content: center;
            min-height: 44px;
        }
        
        .video-url-control {
            display: flex;
            align-items: center;
            gap: 12px;
            margin-bottom: 20px;
            flex-wrap: wrap;
        }
        
        .video-url-control label {
            color: #cdd6f4;
            font-size: 0.9rem;
            font-weight: 500;
            min-width: 80px;
            flex-shrink: 0;
        }
        
        .video-url-control input {
            flex: 1;
            min-width: 300px;
            padding: 10px 12px;
            border-radius: 8px;
            border: 1px solid #585b70;
            background: rgba(49, 50, 68, 0.8);
            color: #cdd6f4;
            font-size: 0.9rem;
            transition: border-color 0.3s, box-shadow 0.3s;
        }
        
        .video-url-control input:focus {
            outline: none;
            border-color: #89dceb;
            box-shadow: 0 0 0 2px rgba(137, 220, 235, 0.2);
        }
        
        .video-url-control input::placeholder {
            color: #6c7086;
        }
        
        /* 自定义 Combobox 样式 */
        .custom-combobox {
            position: relative;
            display: flex;
            align-items: center;
            width: 46%;
        }
        
        .custom-combobox input {
            flex: 1;
            padding-right: 40px;
        }
        
        .combobox-dropdown-btn {
            position: absolute;
            right: 8px;
            background: none;
            border: none;
            color: #89dceb;
            font-size: 14px;
            cursor: pointer;
            padding: 4px;
            z-index: 2;
        }
        
        .combobox-dropdown-btn:hover {
            color: #cba6f7;
        }
        
        .combobox-dropdown {
            position: absolute;
            top: 100%;
            left: 0;
            right: 0;
            background: #1e1e2e;
            border: 1px solid #45475a;
            border-radius: 8px;
            max-height: 200px;
            overflow-y: auto;
            z-index: 1000;
            display: none;
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
        }
        
        .combobox-dropdown.show {
            display: block;
        }
        
        .combobox-option {
            padding: 12px 16px;
            cursor: pointer;
            border-bottom: 1px solid #313244;
            color: #cdd6f4;
            transition: background-color 0.2s;
        }
        
        .combobox-option:last-child {
            border-bottom: none;
        }
        
        .combobox-option:hover {
            background-color: #313244;
            color: #89dceb;
        }
        
        .combobox-option.selected {
            background-color: #45475a;
            color: #cba6f7;
        }
        
        .protocol-select {
            padding: 10px 12px;
            border-radius: 8px;
            border: 1px solid #585b70;
            background: rgba(49, 50, 68, 0.8);
            color: #cdd6f4;
            font-size: 0.9rem;
            min-width: 150px;
            cursor: pointer;
            transition: border-color 0.3s, box-shadow 0.3s;
        }
        
        .protocol-select:focus {
            outline: none;
            border-color: #89dceb;
            box-shadow: 0 0 0 2px rgba(137, 220, 235, 0.2);
        }
        
        .protocol-select option {
            background: #313244;
            color: #cdd6f4;
        }
        

        
        .interval-control {
            display: flex;
            align-items: center;
            gap: 8px;
            background: rgba(49, 50, 68, 0.6);
            padding: 8px 12px;
            border-radius: 8px;
            border: 1px solid #585b70;
            white-space: nowrap;
        }
        
        .interval-control label {
            color: #cdd6f4;
            font-size: 0.9rem;
            white-space: nowrap;
        }
        
        .interval-control input {
            width: 50px;
            padding: 4px 6px;
            border: none;
            background: transparent;
            color: #f9e2af;
            font-weight: bold;
            text-align: center;
        }
        
        .interval-control span {
            color: #a6adc8;
            font-size: 0.9rem;
        }
        
        .image-settings {
            display: flex;
            flex-direction: column;
            gap: 15px;
        }
        
        .draw-settings {
            display: flex;
            flex-direction: column;
            gap: 15px;
        }
        
        .draw-tools {
            background: rgba(49, 50, 68, 0.6);
            border-radius: 8px;
            padding: 12px;
            border: 1px solid #585b70;
        }
        
        .draw-tool-select {
            background: rgba(30, 30, 46, 0.8);
            border: 1px solid #585b70;
            border-radius: 6px;
            padding: 8px 12px;
            color: #cdd6f4;
            font-size: 0.85rem;
            transition: all 0.3s ease;
            flex: 1;
            min-width: 0;
            cursor: pointer;
        }
        
        .draw-tool-select:focus {
            outline: none;
            border-color: #89dceb;
            background: rgba(30, 30, 46, 1);
        }
        
        .draw-style-settings {
            background: rgba(49, 50, 68, 0.6);
            border-radius: 8px;
            padding: 12px;
            border: 1px solid #585b70;
            display: flex;
            flex-direction: column;
            gap: 12px;
        }
        
        .color-picker {
            width: 50px;
            height: 35px;
            border: 1px solid #585b70;
            border-radius: 6px;
            background: transparent;
            cursor: pointer;
            transition: all 0.3s ease;
        }
        
        .color-picker:hover {
            border-color: #89dceb;
            transform: scale(1.05);
        }
        
        .horizontal-slider-container {
            display: flex;
            align-items: center;
            gap: 10px;
            flex: 1;
        }
        
        .horizontal-slider {
            flex: 1;
            height: 6px;
            background: rgba(88, 91, 112, 0.5);
            border-radius: 3px;
            outline: none;
            transition: all 0.3s ease;
        }
        
        .horizontal-slider::-webkit-slider-thumb {
            appearance: none;
            width: 18px;
            height: 18px;
            background: #89dceb;
            border-radius: 50%;
            cursor: pointer;
            transition: all 0.3s ease;
        }
        
        .horizontal-slider::-webkit-slider-thumb:hover {
            background: #74c7ec;
            transform: scale(1.1);
        }
        
        .slider-value {
            color: #f9e2af;
            font-weight: bold;
            font-family: 'Monaco', 'Menlo', 'Consolas', monospace;
            font-size: 0.85rem;
            min-width: 40px;
            text-align: center;
        }
        
        .input-group {
            display: flex;
            flex-direction: column;
            gap: 8px;
        }
        
        .input-group label {
            color: #cdd6f4;
            font-size: 0.9rem;
            font-weight: 500;
        }
        
        .input-group input {
            padding: 10px 12px;
            border-radius: 8px;
            border: 1px solid #585b70;
            background: rgba(49, 50, 68, 0.8);
            color: #cdd6f4;
            transition: border-color 0.3s, box-shadow 0.3s;
        }
        
        .input-group input:focus {
            outline: none;
            border-color: #89dceb;
            box-shadow: 0 0 0 2px rgba(137, 220, 235, 0.2);
        }
        
        .position-group {
            display: flex;
            flex-direction: column;
            gap: 8px;
        }
        
        .tags-header {
            display: flex;
            justify-content: space-between;
            align-items: flex-start;
            margin-bottom: 10px;
            gap: 12px;
        }
        
        .tags-container {
            display: flex;
            flex-direction: column;
            gap: 15px;
        }
        
        .tag-item {
            background: rgba(49, 50, 68, 0.6);
            border: 1px solid #585b70;
            border-radius: 10px;
            padding: 16px;
            transition: all 0.3s ease;
            box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
        }
        
        .tag-item:hover {
            border-color: #89dceb;
            background: rgba(49, 50, 68, 0.8);
        }
        
        .tag-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 12px;
            padding-bottom: 8px;
            border-bottom: 1px solid rgba(88, 91, 112, 0.3);
        }
        
        .tag-title {
            color: #cdd6f4;
            font-weight: 600;
            font-size: 0.9rem;
        }
        
        .tag-title-input {
            background: transparent;
            border: 1px solid rgba(88, 91, 112, 0.3);
            border-radius: 4px;
            color: #cdd6f4;
            font-weight: 600;
            font-size: 0.9rem;
            padding: 4px 8px;
            width: 120px;
            transition: border-color 0.2s ease;
        }
        
        .tag-title-input:focus {
            outline: none;
            border-color: #89dceb;
            box-shadow: 0 0 0 2px rgba(137, 220, 235, 0.2);
        }
        
        .tag-controls {
            display: flex;
            gap: 8px;
        }
        
        .tag-content {
            display: flex;
            flex-direction: column;
            gap: 12px;
        }
        
        .tag-field {
            display: flex;
            flex-direction: row;
            align-items: center;
            gap: 12px;
        }
        
        .tag-field label {
            color: #a6adc8;
            font-size: 0.85rem;
            font-weight: 500;
            min-width: 50px;
            flex-shrink: 0;
        }
        
        .tag-field input {
            background: rgba(30, 30, 46, 0.8);
            border: 1px solid #585b70;
            border-radius: 6px;            
            color: #cdd6f4;
            font-size: 0.85rem;
            transition: all 0.3s ease;
            flex: 1;
            min-width: 0;
        }
        
        .tag-field input:focus {
            outline: none;
            border-color: #89dceb;
            background: rgba(30, 30, 46, 1);
        }
        
        .tag-field select {
            background: rgba(30, 30, 46, 0.8);
            border: 1px solid #585b70;
            border-radius: 6px;
            padding: 8px 12px;
            color: #cdd6f4;
            font-size: 0.85rem;
            transition: all 0.3s ease;
            flex: 1;
            min-width: 0;
            cursor: pointer;
        }
        
        .tag-field select:focus {
            outline: none;
            border-color: #89dceb;
            background: rgba(30, 30, 46, 1);
        }
        
        .tag-field select option {
            background: rgba(30, 30, 46, 1);
            color: #cdd6f4;
            padding: 8px;
        }
        
        /* 水平滑块样式 */
        .tag-field-horizontal {
            align-items: center;
        }
        
        /* 颜色选择器一行布局 */
        .color-row {
            display: flex;
            flex-direction: row;
            align-items: center;
            gap: 20px;
        }
        
        .color-group {
            display: flex;
            flex-direction: row;
            align-items: center;
            gap: 8px;
        }
        
        .color-group label {
            color: #a6adc8;
            font-size: 0.85rem;
            font-weight: 500;
            min-width: auto;
            flex-shrink: 0;
        }
        
        .horizontal-slider-container {
            display: flex;
            flex-direction: row;
            align-items: center;
            gap: 12px;
            flex: 1;
        }
        
        .horizontal-slider {
            -webkit-appearance: none;
            appearance: none;
            width: 100%;
            height: 6px;
            background: rgba(88, 91, 112, 0.5);
            outline: none;
            border-radius: 3px;
            cursor: pointer;
            transition: all 0.3s ease;
        }
        
        .horizontal-slider::-webkit-slider-track {
            width: 100%;
            height: 6px;
            background: rgba(88, 91, 112, 0.5);
            border-radius: 3px;
        }
        
        .horizontal-slider::-webkit-slider-thumb {
            -webkit-appearance: none;
            appearance: none;
            width: 18px;
            height: 18px;
            background: #89dceb;
            border-radius: 50%;
            cursor: pointer;
            transition: all 0.3s ease;
            box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
        }
        
        .horizontal-slider::-webkit-slider-thumb:hover {
            background: #74c7ec;
            transform: scale(1.1);
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
        }
        
        .horizontal-slider::-moz-range-track {
            width: 100%;
            height: 6px;
            background: rgba(88, 91, 112, 0.5);
            border-radius: 3px;
            border: none;
        }
        
        .horizontal-slider::-moz-range-thumb {
            width: 18px;
            height: 18px;
            background: #89dceb;
            border-radius: 50%;
            cursor: pointer;
            border: none;
            transition: all 0.3s ease;
            box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
        }
        
        .horizontal-slider::-moz-range-thumb:hover {
            background: #74c7ec;
            transform: scale(1.1);
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
        }
        
        .slider-value {
            color: #f9e2af;
            font-size: 0.8rem;
            font-weight: bold;
            background: rgba(30, 30, 46, 0.9);
            padding: 4px 8px;
            border-radius: 4px;
            border: 1px solid #585b70;
            min-width: 30px;
            text-align: center;
            flex-shrink: 0;
        }
        
        .tag-controls .btn {
            padding: 8px 16px;
            font-size: 0.8rem;
            min-width: auto;
            border-radius: 6px;
            font-weight: 500;
            transition: all 0.3s ease;
            border: none;
            cursor: pointer;
        }
        
        .tag-controls .btn:hover {
            transform: translateY(-1px);
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
        }
        
        .tag-position {
            background: rgba(30, 30, 46, 0.8);
            border: 1px solid #585b70;
            border-radius: 6px;
            padding: 8px 12px;
            color: #f9e2af !important;
            font-weight: bold !important;
            font-family: 'Monaco', 'Menlo', 'Consolas', monospace;
            font-size: 0.85rem;
            display: inline-block;
            min-width: 120px;
            text-align: center;
            transition: all 0.3s ease;
        }
        
        .tag-position:hover {
            background: rgba(30, 30, 46, 1);
            border-color: #f9e2af;
            box-shadow: 0 0 8px rgba(249, 226, 175, 0.3);
        }
        
        /* Tabs 样式 */
        .tab-header {
            display: flex;
            gap: 8px;
            margin-bottom: 12px;
            border-bottom: 1px solid rgba(88, 91, 112, 0.3);
            padding-bottom: 8px;
        }
        .tab-btn {
            padding: 8px 14px;
            border-radius: 8px 8px 0 0;
            background: rgba(49, 50, 68, 0.6);
            color: #cdd6f4;
            border: 1px solid #585b70;
            border-bottom: none;
            cursor: pointer;
            font-size: 0.9rem;
            transition: all 0.2s ease;
        }
        .tab-btn:hover {
            background: rgba(49, 50, 68, 0.8);
        }
        .tab-btn.active {
            background: rgba(24, 24, 37, 0.8);
            color: #89dceb;
            border-color: #89dceb;
        }
        .tab-pane {
            display: none;
        }
        .tab-pane.active {
            display: block;
        }
        
        .btn-danger {
            background: linear-gradient(135deg, #f38ba8, #eba0ac);
            color: white;
        }
        
        .btn-danger:hover {
            background: linear-gradient(135deg, #eba0ac, #f38ba8);
            transform: translateY(-1px);
        }
        
        .status-text {
            font-size: 0.85rem;
            color: #a6adc8;
            padding: 6px 0;
        }
        
        .btn {
            border: none;
            padding: 8px 16px;
            border-radius: 7px;
            cursor: pointer;
            font-weight: 600;
            font-size: 0.85rem;
            transition: all 0.3s ease;
            box-shadow: 0 3px 10px rgba(0, 0, 0, 0.15);
            position: relative;
            overflow: hidden;
        }
        
        .btn::before {
            content: '';
            position: absolute;
            top: 0;
            left: -100%;
            width: 100%;
            height: 100%;
            background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
            transition: left 0.5s;
        }
        
        .btn:hover::before {
            left: 100%;
        }
        
        .btn:hover {
            transform: translateY(-1px);
            box-shadow: 0 6px 16px rgba(0, 0, 0, 0.25);
        }
        
        .btn:active {
            transform: translateY(0);
            box-shadow: 0 3px 6px rgba(0, 0, 0, 0.2);
        }
        
        .btn-primary {
            background: linear-gradient(135deg, #89b4fa, #74c7ec);
            color: #1e1e2e;
            padding: 12px 24px;
            border-radius: 10px;
            font-size: 0.9rem;
            box-shadow: 0 4px 15px rgba(137, 180, 250, 0.2);
        }
        
        .btn-primary:hover {
            background: linear-gradient(135deg, #74c7ec, #89dceb);
            transform: translateY(-2px);
            box-shadow: 0 8px 25px rgba(137, 180, 250, 0.4);
        }
        
        .btn-secondary {
            background: linear-gradient(135deg, #a6e3a1, #94e2d5);
            color: #1e1e2e;
        }
        
        .btn-toggle {
            background: linear-gradient(135deg, #cba6f7, #f5c2e7);
            color: #1e1e2e;
        }
        
        .btn-stop {
            background: linear-gradient(135deg, #f38ba8, #eba0ac);
            color: #1e1e2e;
        }
        

        
        .info-panel {
            background: rgba(49, 50, 68, 0.8);
            border-radius: 12px;
            padding: 20px;
            box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3);
        }
        
        .info-panel h3 {
            color: #a6e3a1;
            margin-bottom: 15px;
            font-size: 1.3rem;
        }
        
        .info-panel p {
            line-height: 1.6;
            margin-bottom: 12px;
            color: #cdd6f4;
        }
        
        .info-panel code {
            background: rgba(30, 30, 46, 0.6);
            padding: 3px 8px;
            border-radius: 5px;
            font-family: monospace;
            color: #f9e2af;
        }
        
        .status {
            display: flex;
            justify-content: space-between;
            margin-top: 15px;
            padding: 15px 0;
            border-top: 1px solid #45475a;
            border-bottom: 1px solid #45475a;
        }
        
        .status-item {
            text-align: center;
            flex: 1;
            padding: 0 10px;
        }
        
        .status-value {
            font-size: 1.1rem;
            font-weight: bold;
            color: #f9e2af;
            margin-top: 4px;
        }
        
        .status-label {
            font-size: 0.85rem;
            color: #a6adc8;
            font-weight: 500;
        }
        
        footer {
            margin-top: 30px;
            text-align: center;
            color: #6c7086;
            font-size: 0.9rem;
        }
        
        @media (max-width: 768px) {
            .container {
                padding: 15px;
                margin-top: 10px;
            }
            
            .main-content {
                flex-direction: column;
                gap: 15px;
            }
            
            .left-panel {
                min-width: 100%;
            }
            
            .right-panel {
                width: 100%;
            }
            
            .controls {
                padding: 15px;
            }
            
            .control-row {
                grid-template-columns: 1fr;
                gap: 20px;
            }
            
            .control-section {
                padding: 15px;
            }
            
            .button-group {
                grid-template-columns: 1fr;
                gap: 10px;
                margin-bottom: 10px;
            }
            
            .interval-control {
                justify-content: center;
                margin-top: 10px;
            }
            
            .btn {
                width: 100%;
                justify-content: center;
            }
            
            .interval-control {
                justify-content: center;
                margin-top: 10px;
                max-width: 100%;
            }
            
            h1 {
                font-size: 1.8rem;
            }
        }
        
        @media (max-width: 480px) {
            body {
                padding: 10px;
            }
            
            .container {
                padding: 10px;
            }
            
            .controls {
                padding: 10px;
            }
            
            .control-section {
                padding: 12px;
            }
            
            h1 {
                font-size: 1.5rem;
            }
        }
    </style>
</head>
<body>
    <h1>视频流叠加（AR+AI demo）</h1>
    
    <div class="container">
        <div class="main-content">
            <div class="left-panel">
                <div class="video-container">
                    <canvas id="videoCanvas"></canvas>
                </div>
                
                <div class="info-panel">            
                    <div class="status">
                        <div class="status-item">
                            <div class="status-label">视频状态</div>
                            <div id="videoStatus" class="status-value">未播放</div>
                        </div>
                        <div class="status-item">
                            <div class="status-label">帧率</div>
                            <div id="fps" class="status-value">0 FPS</div>
                        </div>
                        <div class="status-item">
                            <div class="status-label">分辨率</div>
                            <div id="resolution" class="status-value">0×0</div>
                        </div>
                        <div class="status-item">
                            <div class="status-label">当前协议</div>
                            <div id="currentProtocol" class="status-value">HLS</div>
                        </div>
                        <div class="status-item">
                            <div class="status-label">播放器</div>
                            <div id="currentPlayer" class="status-value">HLS.js</div>
                        </div>
                    </div>
                </div>

                <div class="controls">
                    <div class="control-row">
                        <div class="control-section">
                            <h3>🎮 视频控制</h3>
                            <div class="video-url-control">
                                <div class="custom-combobox">
                                    <input type="text" id="videoUrlInput" value="" placeholder="输入视频流地址 (支持HLS/RTMP/HTTP-FLV)">
                                    <button type="button" class="combobox-dropdown-btn" id="comboboxDropdownBtn">▼</button>
                                    <div class="combobox-dropdown" id="comboboxDropdown">
                                        <div class="combobox-option" data-value="http://10.56.131.120:7086/live/cameraid/1000039%243/substream/2.m3u8">📹 小广场</div>
                                        <div class="combobox-option" data-value="http://10.254.16.92:82/live/cameraid/1000051%245/substream/2.m3u8">🎬 路边</div>                                       
                                        <div class="combobox-option" data-value="http://10.56.131.120:7086/live/cameraid/1000054%241/substream/1.m3u8">🎨 储物间</div>
                                        <div class="combobox-option" data-value="https://demo.unified-streaming.com/k8s/features/stable/video/tears-of-steel/tears-of-steel.ism/.m3u8">🎭 公网测试</div>
                                    </div>
                                </div>
                              
                                <select id="protocolSelect" class="protocol-select">
                                    <option value="auto">🔍 自动检测</option>
                                    <option value="hls">📺 HLS (.m3u8)</option>
                                    <option value="flv">🎬 HTTP-FLV (.flv)</option>
                                    <option value="rtmp" disabled>📡 RTMP (rtmp://)</option>
                                </select>
                                <button id="updateVideoBtn" class="btn btn-primary">🔄 更新源</button>
                            </div>

                            <div class="button-group">
                                <button id="playPauseBtn" class="btn btn-toggle">▶️ 播放视频</button>
                                <button id="frameCaptureBtn" class="btn btn-secondary">📸 开始抓帧</button>
                                <div class="interval-control">
                                    <label for="captureInterval">间隔:</label>
                                    <input type="number" id="captureInterval" value="3" min="1" max="60">
                                    <span>秒</span>
                                </div>
                            </div>
                            <div id="captureStatus" class="status-text">
                                帧抓取: 未启动
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            
            <div class="right-panel">
                <div class="control-section">
                    <div class="tab-header">
                        <button class="tab-btn active" data-tab="image">🏷️ 图片标签</button>
                        <button class="tab-btn" data-tab="text">📝 文字标签</button>
                        <button class="tab-btn" data-tab="draw">🎨 绘制标签</button>
                    </div>
                    
                    <div id="tab-image" class="tab-pane active">
                        <div class="image-settings">
                            <div class="tags-header">
                                <button id="addTagBtn" class="btn btn-primary">🖼️ 添加图片</button>
                                <button id="editModeBtn" class="btn btn-secondary">🔍 缩放图片</button>
                            </div>
                            <div id="tagsContainer" class="tags-container">
                                <!-- 标签项将通过JavaScript动态添加 -->
                            </div>
                        </div>
                    </div>
                    
                    <div id="tab-text" class="tab-pane">
                        <div class="text-settings">
                            <div class="tags-header">
                                <button id="addTextBtn" class="btn btn-primary">➕ 添加文字</button>
                            </div>
                            <div id="textTagsContainer" class="tags-container">
                                <!-- 文字标签项将通过JavaScript动态添加 -->
                            </div>
                        </div>
                    </div>
                    
                    <div id="tab-draw" class="tab-pane">
                        <div class="draw-settings">
                            <div class="tags-header">
                                <button id="drawModeBtn" class="btn btn-secondary">✏️ 绘制模式</button>
                            </div>
                            
                            <!-- 绘制工具选择 -->
                            <div class="draw-tools">
                                <div class="tag-field">
                                    <label>绘制工具:</label>
                                    <select id="drawToolSelect" class="draw-tool-select">                                       
                                        <option value="lasso">🔗 套索绘制</option>
                                         <option value="pen">🖊️ 钢笔绘制</option>
                                    </select>
                                </div>
                            </div>
                            
                            <!-- 样式设置 -->
                            <div class="draw-style-settings">
                                <div class="tag-field color-row">
                                    <div class="color-group">
                                        <label>填充色:</label>
                                        <input type="color" id="fillColorPicker" value="#ff6b6b" class="color-picker">
                                    </div>
                                    <div class="color-group">
                                        <label>边框色:</label>
                                        <input type="color" id="strokeColorPicker" value="#4ecdc4" class="color-picker">
                                    </div>
                                </div>
                                <div class="tag-field">
                                    <label>透明度:</label>
                                    <div class="horizontal-slider-container">
                                        <input type="range" id="opacitySlider" class="horizontal-slider" min="0" max="1" step="0.1" value="0.7">
                                        <span id="opacityValue" class="slider-value">0.7</span>
                                    </div>
                                </div>
                                <div class="tag-field">
                                    <label>线条宽度:</label>
                                    <div class="horizontal-slider-container">
                                        <input type="range" id="strokeWidthSlider" class="horizontal-slider" min="1" max="10" step="1" value="2">
                                        <span id="strokeWidthValue" class="slider-value">2px</span>
                                    </div>
                                </div>
                            </div>
                            
                            <!-- 绘制项目列表 -->
                            <div id="drawItemsContainer" class="tags-container">
                                <!-- 绘制项目将通过JavaScript动态添加 -->
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        

    </div>
    
    <footer>
        Canvas视频流PNG标签叠加演示 | 基于HLS.js实现
    </footer>

    <script>
        document.addEventListener('DOMContentLoaded', function() {
            
            // 获取DOM元素
            const canvas = document.getElementById('videoCanvas');
            const ctx = canvas.getContext('2d');
            const playPauseBtn = document.getElementById('playPauseBtn');
            const addTagBtn = document.getElementById('addTagBtn');
            const addTextBtn = document.getElementById('addTextBtn');
            const editModeBtn = document.getElementById('editModeBtn');
            const tagsContainer = document.getElementById('tagsContainer');
            const textTagsContainer = document.getElementById('textTagsContainer');
            const videoStatus = document.getElementById('videoStatus');
            const fpsDisplay = document.getElementById('fps');
            const resolutionDisplay = document.getElementById('resolution');
            const frameCaptureBtn = document.getElementById('frameCaptureBtn');
            const captureStatus = document.getElementById('captureStatus');
            const captureIntervalInput = document.getElementById('captureInterval');
            const videoUrlInput = document.getElementById('videoUrlInput');
            const updateVideoBtn = document.getElementById('updateVideoBtn');
            const protocolSelect = document.getElementById('protocolSelect');
            const currentProtocol = document.getElementById('currentProtocol');
            const currentPlayer = document.getElementById('currentPlayer');
            
            // Tabs 元素
            const tabButtons = document.querySelectorAll('.tab-btn');
            const tabImagePane = document.getElementById('tab-image');
            const tabTextPane = document.getElementById('tab-text');
            const tabDrawPane = document.getElementById('tab-draw');
            
            // 绘制功能元素
            const drawModeBtn = document.getElementById('drawModeBtn');
            const drawToolSelect = document.getElementById('drawToolSelect');
            const fillColorPicker = document.getElementById('fillColorPicker');
            const strokeColorPicker = document.getElementById('strokeColorPicker');
            const opacitySlider = document.getElementById('opacitySlider');
            const opacityValue = document.getElementById('opacityValue');
            const strokeWidthSlider = document.getElementById('strokeWidthSlider');
            const strokeWidthValue = document.getElementById('strokeWidthValue');
            const drawItemsContainer = document.getElementById('drawItemsContainer');

            // 视频流地址（可动态更新）
            let videoUrl = videoUrlInput.value;
            
            function switchTab(name) {
                // 更新按钮激活态
                tabButtons.forEach(btn => {
                    btn.classList.toggle('active', btn.dataset.tab === name);
                });
                // 显示对应面板
                tabImagePane.classList.toggle('active', name === 'image');
                tabTextPane.classList.toggle('active', name === 'text');
                tabDrawPane.classList.toggle('active', name === 'draw');
            }
            
            tabButtons.forEach(btn => {
                btn.addEventListener('click', () => switchTab(btn.dataset.tab));
            });
            // 默认显示图片标签页
            switchTab('image');
            
            // 自定义 Combobox 功能
            function initCustomCombobox() {
                const input = document.getElementById('videoUrlInput');
                const dropdownBtn = document.getElementById('comboboxDropdownBtn');
                const dropdown = document.getElementById('comboboxDropdown');
                const options = document.querySelectorAll('.combobox-option');
                
                if (!input || !dropdownBtn || !dropdown) {
                    console.error('❌ Combobox elements not found');
                    return;
                }
                
                // 切换下拉列表显示/隐藏
                function toggleDropdown() {
                    dropdown.classList.toggle('show');
                    if (dropdown.classList.contains('show')) {
                        dropdownBtn.textContent = '▲';
                    } else {
                        dropdownBtn.textContent = '▼';
                    }
                }
                
                // 隐藏下拉列表
                function hideDropdown() {
                    dropdown.classList.remove('show');
                    dropdownBtn.textContent = '▼';
                }
                
                // 选择选项
                function selectOption(value, text) {
                    input.value = value;
                    hideDropdown();
                    console.log('✅ Selected:', text);
                }
                
                // 下拉按钮点击事件
                dropdownBtn.addEventListener('click', function(e) {
                    e.preventDefault();
                    e.stopPropagation();
                    toggleDropdown();
                });
                
                // 输入框点击事件
                input.addEventListener('click', function() {
                    toggleDropdown();
                });
                
                // 选项点击事件
                options.forEach(option => {
                    option.addEventListener('click', function() {
                        const value = this.getAttribute('data-value');
                        const text = this.textContent;
                        selectOption(value, text);
                    });
                });
                
                // 点击外部关闭下拉列表
                document.addEventListener('click', function(e) {
                    if (!input.contains(e.target) && !dropdownBtn.contains(e.target) && !dropdown.contains(e.target)) {
                        hideDropdown();
                    }
                });
                
                // 键盘支持
                input.addEventListener('keydown', function(e) {
                    if (e.key === 'ArrowDown') {
                        e.preventDefault();
                        if (!dropdown.classList.contains('show')) {
                            toggleDropdown();
                        }
                    } else if (e.key === 'Escape') {
                        hideDropdown();
                    }
                });
                
                console.log('✅ Custom combobox initialized with', options.length, 'options');
            }
            
            // 初始化自定义combobox
            initCustomCombobox();
            
            // 创建视频元素（不在DOM中显示）
            const video = document.createElement('video');
            video.muted = true; // 静音播放避免自动播放限制
            video.playsInline = true;
            
            // 播放器管理
            let currentPlayerType = 'hls'; // 当前播放器类型: hls, flv, rtmp
            let playerInstances = {
                hls: null,    // HLS.js实例
                flv: null,    // flv.js实例  
                video: null   // Video.js实例 (用于RTMP)
            };
            
            // 多标签管理
            let tags = []; // 存储所有图片标签的数组
            let tagIdCounter = 0; // 图片标签ID计数器
            
            // 文字标签管理
            let textTags = []; // 存储所有文字标签的数组
            let textTagIdCounter = 0; // 文字标签ID计数器

            // 绘制功能管理
            let drawItems = []; // 存储所有绘制项目的数组
            let drawItemIdCounter = 0; // 绘制项目ID计数器
            let isDrawing = false; // 是否正在绘制
            let currentDrawPath = []; // 当前绘制路径
            let drawMode = false; // 是否处于绘制模式
            let currentDrawTool = 'lasso'; // 当前绘制工具 ('pen' 或 'lasso')
            let drawSettings = {
                fillColor: '#ff6b6b',
                strokeColor: '#4ecdc4',
                opacity: 0.7,
                strokeWidth: 2
            };
            
            // 拖动功能相关变量
            let isDragging = false; // 是否正在拖动
            let draggedTag = null; // 当前被拖动的标签
            let draggedTextTag = null; // 当前被拖动的文字标签
            let dragOffset = { x: 0, y: 0 }; // 拖动偏移量
            let isDraggingDrawItem = false; // 是否正在拖动绘制项目
            let draggedDrawItem = null; // 当前被拖动的绘制项目
            let drawItemDragOffset = { x: 0, y: 0 }; // 绘制项目拖动偏移量
            
            // 编辑模式和缩放相关变量
            let isEditMode = false; // 是否处于编辑模式
            let isResizing = false; // 是否正在缩放
            let resizeHandle = null; // 当前缩放控制点 ('nw', 'ne', 'sw', 'se')
            let resizeStartSize = { width: 0, height: 0 }; // 缩放开始时的尺寸
            let resizeStartPos = { x: 0, y: 0 }; // 缩放开始时的鼠标位置
            let hoveredHandle = null; // 当前悬停的控制点
            let hoveredTag = null; // 当前悬停控制点所属的标签

            
            // 动画和性能监控变量
            let animationFrameId;
            let lastTimestamp = 0;
            let frameCount = 0;
            let fps = 0;
            
            // 帧抓取功能相关变量
            let isCapturing = false;
            let captureInterval = null;
            let captureCount = 0;
            
            // 更新Canvas尺寸以匹配视频
            function updateCanvasSize() {
                if (video.videoWidth > 0 && video.videoHeight > 0) {
                    canvas.width = video.videoWidth;
                    canvas.height = video.videoHeight;
                    resolutionDisplay.textContent = `${canvas.width}×${canvas.height}`;
                }
            }
            
            // 多标签管理函数
            
            /**
             * 创建新标签
             */
            function createTag() {
                const tagId = ++tagIdCounter;
                
                // AR素材图片数组
                const arImages = [
                    'images/ar-cube.svg',
                    'images/ar-sphere.svg', 
                    'images/ar-diamond.svg',
                    'images/ar-star.svg',
                    'images/ar-triangle.svg'
                ];
                
                // 随机选择一个AR素材
                const randomArImage = arImages[Math.floor(Math.random() * arImages.length)];
                
                const tag = {
                    id: tagId,
                    imageUrl: randomArImage,
                    x: 0,
                    y: 0,
                    width: 80,
                    height: 80,
                    text: `点位${tagId}`,
                    image: new Image(),
                    loaded: false,
                    // 动画配置
                    animationType: 'none', // 'none', 'blink', 'scale'
                    animationStartTime: performance.now(), // 动画开始时间戳
                    animationSpeed: 1.0 // 动画速度倍数
                };
                
                // 设置图片跨域
                tag.image.crossOrigin = "Anonymous";
                
                // 加载图片
                tag.image.onload = () => {
                    tag.loaded = true;
                    console.log(`标签 ${tagId} 图片加载完成`);
                };
                
                tag.image.onerror = () => {
                    console.error(`标签 ${tagId} 图片加载失败`);
                };
                
                tag.image.src = tag.imageUrl;
                
                tags.push(tag);
                renderTagItem(tag);
                
                return tag;
            }
            
            /**
             * 删除标签
             */
            function deleteTag(tagId) {
                const index = tags.findIndex(tag => tag.id === tagId);
                if (index !== -1) {
                    tags.splice(index, 1);
                    const tagElement = document.querySelector(`[data-tag-id="${tagId}"]`);
                    if (tagElement) {
                        tagElement.remove();
                    }
                }
            }
            
            /**
             * 创建新文字标签
             */
            function createTextTag() {
                const textTagId = ++textTagIdCounter;
                
                const textTag = {
                    id: textTagId,
                    text: `文字${textTagId}`,
                    x: 100,
                    y: 100,
                    fontSize: 24,
                    fontColor: '#ffffff',
                    backgroundColor: 'rgba(0, 0, 0, 0.5)'
                    // width 和 height 将在绘制时动态计算
                };
                
                textTags.push(textTag);
                renderTextTagItem(textTag);
                
                return textTag;
            }
            
            /**
             * 删除文字标签
             */
            function deleteTextTag(textTagId) {
                const index = textTags.findIndex(tag => tag.id === textTagId);
                if (index !== -1) {
                    textTags.splice(index, 1);
                    const tagElement = document.querySelector(`[data-text-tag-id="${textTagId}"]`);
                    if (tagElement) {
                        tagElement.remove();
                    }
                }
            }
            
            // 绘制功能函数
            
            /**
             * 创建新的绘制项目
             */
            function createDrawItem() {
                const drawItemId = ++drawItemIdCounter;
                
                const drawItem = {
                    id: drawItemId,
                    path: [],
                    fillColor: drawSettings.fillColor,
                    strokeColor: drawSettings.strokeColor,
                    opacity: drawSettings.opacity,
                    strokeWidth: drawSettings.strokeWidth,
                    tool: currentDrawTool,
                    closed: false
                };
                
                drawItems.push(drawItem);
                renderDrawItem(drawItem);
                
                console.log('✅ 创建绘制项目:', drawItem);
                return drawItem;
            }
            
            /**
             * 删除绘制项目
             */
            function deleteDrawItem(drawItemId) {
                const index = drawItems.findIndex(item => item.id === drawItemId);
                if (index !== -1) {
                    drawItems.splice(index, 1);
                    const itemElement = document.querySelector(`[data-draw-item-id="${drawItemId}"]`);
                    if (itemElement) {
                        itemElement.remove();
                    }
                }
            }
            
            /**
             * 渲染绘制项目到DOM
             */
            function renderDrawItem(drawItem) {
                const itemElement = document.createElement('div');
                itemElement.className = 'tag-item';
                itemElement.setAttribute('data-draw-item-id', drawItem.id);
                
                itemElement.innerHTML = `
                    <div class="tag-header">
                        <input type="text" class="tag-title-input" value="绘制 #${drawItem.id}" data-draw-item-id="${drawItem.id}">
                        <div class="tag-controls">
                            <button class="btn btn-danger delete-draw-btn" data-draw-item-id="${drawItem.id}">删除</button>
                        </div>
                    </div>
                    <div class="tag-content">
                        <div class="tag-field">
                            <label>工具:</label>
                            <span>${drawItem.tool === 'pen' ? '🖊️ 钢笔' : '🔗 套索'}</span>
                        </div>
                        <div class="tag-field color-row">
                            <div class="color-group">
                                <label>填充色:</label>
                                <input type="color" class="color-picker draw-fill-color" value="${drawItem.fillColor}" data-draw-item-id="${drawItem.id}">
                            </div>
                            <div class="color-group">
                                <label>边框色:</label>
                                <input type="color" class="color-picker draw-stroke-color" value="${drawItem.strokeColor}" data-draw-item-id="${drawItem.id}">
                            </div>
                        </div>
                        <div class="tag-field">
                            <label>透明度:</label>
                            <div class="horizontal-slider-container">
                                <input type="range" class="horizontal-slider draw-opacity" min="0" max="1" step="0.1" value="${drawItem.opacity}" data-draw-item-id="${drawItem.id}">
                                <span class="slider-value draw-opacity-value">${drawItem.opacity}</span>
                            </div>
                        </div>
                        <div class="tag-field">
                            <label>线条宽度:</label>
                            <div class="horizontal-slider-container">
                                <input type="range" class="horizontal-slider draw-stroke-width" min="1" max="10" step="1" value="${drawItem.strokeWidth}" data-draw-item-id="${drawItem.id}">
                                <span class="slider-value draw-stroke-width-value">${drawItem.strokeWidth}px</span>
                            </div>
                        </div>
                        <div class="tag-field">
                            <label>状态:</label>
                            <span>${drawItem.closed ? '✅ 已闭合' : '⏳ 绘制中'}</span>
                        </div>
                    </div>
                `;
                
                drawItemsContainer.appendChild(itemElement);
                
                // 绑定删除按钮事件
                const deleteBtn = itemElement.querySelector('.delete-draw-btn');
                deleteBtn.addEventListener('click', function() {
                    deleteDrawItem(drawItem.id);
                });
                
                // 绑定样式编辑事件
                const fillColorInput = itemElement.querySelector('.draw-fill-color');
                const strokeColorInput = itemElement.querySelector('.draw-stroke-color');
                const opacityInput = itemElement.querySelector('.draw-opacity');
                const strokeWidthInput = itemElement.querySelector('.draw-stroke-width');
                const opacityValue = itemElement.querySelector('.draw-opacity-value');
                const strokeWidthValue = itemElement.querySelector('.draw-stroke-width-value');
                
                fillColorInput.addEventListener('change', function() {
                    updateDrawItemStyle(drawItem.id, 'fillColor', this.value);
                });
                
                strokeColorInput.addEventListener('change', function() {
                    updateDrawItemStyle(drawItem.id, 'strokeColor', this.value);
                });
                
                opacityInput.addEventListener('input', function() {
                    updateDrawItemStyle(drawItem.id, 'opacity', parseFloat(this.value));
                    opacityValue.textContent = this.value;
                });
                
                strokeWidthInput.addEventListener('input', function() {
                    updateDrawItemStyle(drawItem.id, 'strokeWidth', parseInt(this.value));
                    strokeWidthValue.textContent = this.value + 'px';
                });
            }
            
            /**
             * 更新绘制项目样式
             */
            function updateDrawItemStyle(drawItemId, property, value) {
                const drawItem = drawItems.find(item => item.id === drawItemId);
                if (drawItem) {
                    drawItem[property] = value;
                    console.log(`🎨 更新绘制项目 #${drawItemId} 的 ${property}:`, value);
                    
                    // 触发重绘以显示样式变化
                    if (!animationFrameId) {
                        animationFrameId = requestAnimationFrame(drawFrame);
                    }
                }
            }
            
            /**
             * 开始绘制模式
             */
            function startDrawMode() {
                drawMode = true;
                drawModeBtn.textContent = '🛑 退出绘制';
                drawModeBtn.classList.remove('btn-secondary');
                drawModeBtn.classList.add('btn-danger');
                canvas.style.cursor = 'crosshair';
                console.log('✅ 进入绘制模式');
            }
            
            /**
             * 退出绘制模式
             */
            function exitDrawMode() {
                drawMode = false;
                isDrawing = false;
                currentDrawPath = [];
                drawModeBtn.textContent = '✏️ 绘制模式';
                drawModeBtn.classList.remove('btn-danger');
                drawModeBtn.classList.add('btn-secondary');
                canvas.style.cursor = 'default';
                console.log('✅ 退出绘制模式');
            }
            
            /**
             * 检测路径是否闭合
             */
            function isPathClosed(path) {
                if (path.length < 3) return false;
                
                const firstPoint = path[0];
                const lastPoint = path[path.length - 1];
                const distance = Math.sqrt(
                    Math.pow(lastPoint.x - firstPoint.x, 2) + 
                    Math.pow(lastPoint.y - firstPoint.y, 2)
                );
                
                return distance < 20; // 20像素内认为闭合
            }
            
            /**
             * 绘制所有绘制项目
             */
            function drawAllDrawItems() {
                drawItems.forEach(item => {
                    if (item.path.length > 1) {
                        drawPath(item);
                    }
                });
                
                // 绘制当前正在绘制的路径
                if (isDrawing && currentDrawPath.length > 1) {
                    const tempItem = {
                        path: currentDrawPath,
                        fillColor: drawSettings.fillColor,
                        strokeColor: drawSettings.strokeColor,
                        opacity: drawSettings.opacity,
                        strokeWidth: drawSettings.strokeWidth,
                        closed: false
                    };
                    drawPath(tempItem);
                }
            }
            
            /**
             * 绘制单个路径
             */
            function drawPath(item) {
                if (item.path.length < 2) return;
                
                ctx.save();
                ctx.globalAlpha = item.opacity;
                ctx.strokeStyle = item.strokeColor;
                ctx.lineWidth = item.strokeWidth;
                ctx.lineCap = 'round';
                ctx.lineJoin = 'round';
                
                ctx.beginPath();
                ctx.moveTo(item.path[0].x, item.path[0].y);
                
                for (let i = 1; i < item.path.length; i++) {
                    ctx.lineTo(item.path[i].x, item.path[i].y);
                }
                
                if (item.closed) {
                    ctx.closePath();
                    ctx.fillStyle = item.fillColor;
                    ctx.fill();
                }
                
                ctx.stroke();
                ctx.restore();
            }
            
            /**
             * 渲染标签项到DOM
             */
            function renderTagItem(tag) {
                const tagElement = document.createElement('div');
                tagElement.className = 'tag-item';
                tagElement.setAttribute('data-tag-id', tag.id);
                
                tagElement.innerHTML = `
                    <div class="tag-header">
                        <span class="tag-title">标签 #${tag.id}</span>
                        <div class="tag-controls">
                            <button class="btn btn-danger delete-tag-btn" data-tag-id="${tag.id}">删除</button>
                        </div>
                    </div>
                    <div class="tag-content">
                        <div class="tag-field">
                            <label>地址:</label>
                            <div class="custom-combobox">
                                <input type="text" class="tag-url-input" value="${tag.imageUrl}" data-tag-id="${tag.id}" placeholder="输入图片URL">
                                <button type="button" class="combobox-dropdown-btn image-combobox-btn" data-tag-id="${tag.id}">▼</button>
                                <div class="combobox-dropdown image-combobox-dropdown" data-tag-id="${tag.id}">
                                    <div class="combobox-option" data-value="images/ar-cube.svg">🧊 AR立方体</div>
                                    <div class="combobox-option" data-value="images/ar-diamond.svg">💎 AR钻石</div>
                                    <div class="combobox-option" data-value="images/ar-sphere.svg">🌐 AR球体</div>
                                    <div class="combobox-option" data-value="images/ar-star.svg">⭐ AR星星</div>
                                    <div class="combobox-option" data-value="images/ar-triangle.svg">🔺 AR三角形</div>
                                    <div class="combobox-option" data-value="images/cool-emoji.svg">😎 酷表情</div>
                                    <div class="combobox-option" data-value="images/heart-eyes-emoji.svg">😍 爱心眼表情</div>
                                    <div class="combobox-option" data-value="images/laugh-emoji.svg">😂 大笑表情</div>
                                    <div class="combobox-option" data-value="images/smile-emoji.svg">😊 微笑表情</div>      
                                    <div class="combobox-option" data-value="images/wink-emoji.svg">😉 眨眼表情</div>
                                    <div class="combobox-option" data-value="images/m1.png">🖼️ 示例图片</div>
                                </div>
                            </div>
                        </div>
                        <div class="tag-field">
                            <label>描述:</label>
                            <input type="text" class="tag-text-input" value="${tag.text}" data-tag-id="${tag.id}" placeholder="输入标签描述">
                        </div>
                        <div class="tag-field">
                            <label>位置:</label>
                            <span class="tag-position" data-tag-id="${tag.id}" style="color: #f9e2af; font-weight: bold;">X: ${Math.round(tag.x)}, Y: ${Math.round(tag.y)}</span>
                        </div>
                        <div class="tag-field">
                            <label>动画:</label>
                            <select class="tag-animation-select" data-tag-id="${tag.id}">
                                <option value="none" ${tag.animationType === 'none' ? 'selected' : ''}>无动画</option>
                                <option value="blink" ${tag.animationType === 'blink' ? 'selected' : ''}>闪烁</option>
                                <option value="scale" ${tag.animationType === 'scale' ? 'selected' : ''}>缩放</option>
                            </select>
                        </div>
                    </div>
                `;
                
                tagsContainer.appendChild(tagElement);
                
                // 添加事件监听器
                const deleteBtn = tagElement.querySelector('.delete-tag-btn');
                const urlInput = tagElement.querySelector('.tag-url-input');
                const textInput = tagElement.querySelector('.tag-text-input');
                const animationSelect = tagElement.querySelector('.tag-animation-select');
                
                deleteBtn.addEventListener('click', () => deleteTag(tag.id));
                urlInput.addEventListener('input', (e) => updateTagUrl(tag.id, e.target.value));
                textInput.addEventListener('input', (e) => updateTagText(tag.id, e.target.value));
                animationSelect.addEventListener('change', (e) => updateTagAnimation(tag.id, e.target.value));
            }
            
            /**
             * 渲染文字标签项到DOM
             */
            function renderTextTagItem(textTag) {
                const tagElement = document.createElement('div');
                tagElement.className = 'tag-item';
                tagElement.setAttribute('data-text-tag-id', textTag.id);
                
                tagElement.innerHTML = `
                    <div class="tag-header">
                        <span class="tag-title">文字 #${textTag.id}</span>
                        <div class="tag-controls">
                            <button class="btn btn-danger delete-text-tag-btn" data-text-tag-id="${textTag.id}">删除</button>
                        </div>
                    </div>
                    <div class="tag-content">
                        <div class="tag-field">
                            <label>文字:</label>
                            <input type="text" class="text-tag-text-input" value="${textTag.text}" data-text-tag-id="${textTag.id}" placeholder="输入文字内容">
                        </div>
                        <div class="tag-field tag-field-horizontal">
                            <label>字号:</label>
                            <div class="horizontal-slider-container">
                                <input type="range" class="text-tag-size-input horizontal-slider" value="${textTag.fontSize}" data-text-tag-id="${textTag.id}" min="12" max="72">
                                <span class="slider-value">${textTag.fontSize}</span>
                            </div>
                        </div>
                        <div class="tag-field">
                            <label>颜色:</label>
                            <input type="color" class="text-tag-color-input" value="${textTag.fontColor}" data-text-tag-id="${textTag.id}">
                        </div>
                        <div class="tag-field">
                            <label>位置:</label>
                            <span class="text-tag-position" data-text-tag-id="${textTag.id}" style="color: #f9e2af; font-weight: bold;">X: ${Math.round(textTag.x)}, Y: ${Math.round(textTag.y)}</span>
                        </div>
                    </div>
                `;
                
                textTagsContainer.appendChild(tagElement);
                
                // 添加事件监听器
                const deleteBtn = tagElement.querySelector('.delete-text-tag-btn');
                const textInput = tagElement.querySelector('.text-tag-text-input');
                const sizeInput = tagElement.querySelector('.text-tag-size-input');
                const colorInput = tagElement.querySelector('.text-tag-color-input');
                const sliderValue = tagElement.querySelector('.slider-value');
                
                deleteBtn.addEventListener('click', () => deleteTextTag(textTag.id));
                textInput.addEventListener('input', (e) => updateTextTagText(textTag.id, e.target.value));
                sizeInput.addEventListener('input', (e) => {
                    const newSize = parseInt(e.target.value);
                    updateTextTagSize(textTag.id, newSize);
                    // 实时更新滑块值显示
                    if (sliderValue) {
                        sliderValue.textContent = newSize;
                    }
                });
                colorInput.addEventListener('input', (e) => updateTextTagColor(textTag.id, e.target.value));
            }
            

            
            /**
             * 更新标签图片URL
             */
            function updateTagUrl(tagId, newUrl) {
                const tag = tags.find(t => t.id === tagId);
                if (tag) {
                    tag.imageUrl = newUrl;
                    tag.loaded = false;
                    tag.image.src = newUrl;
                }
            }
            
            /**
             * 更新标签文本
             */
            function updateTagText(tagId, newText) {
                const tag = tags.find(t => t.id === tagId);
                if (tag) {
                    tag.text = newText;
                }
            }
            
            /**
             * 更新标签动画类型
             */
            function updateTagAnimation(tagId, animationType) {
                const tag = tags.find(t => t.id === tagId);
                if (tag) {
                    tag.animationType = animationType;
                    tag.animationStartTime = performance.now(); // 重置动画开始时间
                    console.log(`🎬 标签 #${tagId} 动画类型更新为: ${animationType}`);
                }
            }
            
            /**
             * 更新标签位置显示
             */
            function updateTagPositionDisplay(tag) {
                const positionElement = document.querySelector(`.tag-position[data-tag-id="${tag.id}"]`);
                if (positionElement) {
                    positionElement.textContent = `X: ${Math.round(tag.x)}, Y: ${Math.round(tag.y)}`;
                }
            }
            
            /**
             * 更新文字标签文本
             */
            function updateTextTagText(textTagId, newText) {
                const textTag = textTags.find(t => t.id === textTagId);
                if (textTag) {
                    textTag.text = newText;
                }
            }
            
            /**
             * 更新文字标签字号
             */
            function updateTextTagSize(textTagId, newSize) {
                const textTag = textTags.find(t => t.id === textTagId);
                if (textTag) {
                    textTag.fontSize = newSize;
                }
            }
            
            /**
             * 更新文字标签颜色
             */
            function updateTextTagColor(textTagId, newColor) {
                const textTag = textTags.find(t => t.id === textTagId);
                if (textTag) {
                    textTag.fontColor = newColor;
                }
            }
            
            /**
             * 更新文字标签位置显示
             */
            function updateTextTagPositionDisplay(textTag) {
                const positionElement = document.querySelector(`.text-tag-position[data-text-tag-id="${textTag.id}"]`);
                if (positionElement) {
                    positionElement.textContent = `X: ${Math.round(textTag.x)}, Y: ${Math.round(textTag.y)}`;
                }
            }
            
            /**
             * 抓取当前视频帧并转换为图片
             * @returns {Promise<Blob>} 返回图片Blob对象
             */
            function captureFrame() {
                return new Promise((resolve, reject) => {
                    try {
                        // 创建一个临时canvas来抓取当前帧
                        const tempCanvas = document.createElement('canvas');
                        const tempCtx = tempCanvas.getContext('2d');
                        
                        // 设置临时canvas尺寸与视频相同
                        tempCanvas.width = video.videoWidth;
                        tempCanvas.height = video.videoHeight;
                        
                        // 绘制当前视频帧到临时canvas
                        tempCtx.drawImage(video, 0, 0, tempCanvas.width, tempCanvas.height);
                        
                        // 转换为Blob
                        tempCanvas.toBlob((blob) => {
                            if (blob) {
                                resolve(blob);
                            } else {
                                reject(new Error('无法生成图片Blob'));
                            }
                        }, 'image/png', 0.9);
                        
                    } catch (error) {
                        reject(error);
                    }
                });
            }
            
            /**
             * 上传图片到/upload接口
             * @param {Blob} imageBlob 图片Blob对象
             * @returns {Promise<Object>} 返回服务器响应
             */
            async function uploadFrame(imageBlob) {
                try {
                    const formData = new FormData();
                    formData.append('file', imageBlob, `frame_${captureCount}_${Date.now()}.png`);
                    
                    const response = await fetch('/upload', {
                        method: 'POST',
                        body: formData
                    });
                    
                    if (!response.ok) {
                        throw new Error(`HTTP错误: ${response.status} ${response.statusText}`);
                    }
                    
                    const result = await response.json();
                    return result;
                    
                } catch (error) {
                    throw error;
                }
            }
            
            /**
             * 计算图片的实际绘制区域
             * @param {Object} tag 标签对象
             * @returns {Object} 包含实际绘制位置和尺寸的对象
             */
            function getImageDrawBounds(tag) {
                const imgW = tag.image.naturalWidth || tag.image.width || 1;
                const imgH = tag.image.naturalHeight || tag.image.height || 1;
                const boxW = tag.width;
                const boxH = tag.height;
                const imgRatio = imgW / imgH;
                const boxRatio = boxW / boxH;

                let drawW, drawH;
                if (imgRatio > boxRatio) {
                    // 图片更宽，宽度铺满，按比例缩放高度
                    drawW = boxW;
                    drawH = Math.round(boxW / imgRatio);
                } else {
                    // 图片更高，高度铺满，按比例缩放宽度
                    drawH = boxH;
                    drawW = Math.round(boxH * imgRatio);
                }
                const offsetX = Math.round(tag.x + (boxW - drawW) / 2);
                const offsetY = Math.round(tag.y + (boxH - drawH) / 2);

                return { x: offsetX, y: offsetY, width: drawW, height: drawH };
            }

            // 控制点配置常量
            const HANDLE_CONFIG = {
                size: 12,           // 控制点视觉大小
                distance: -5,        // 控制点距离图片边缘的固定像素距离
                clickableSize: 36   // 可点击区域大小，比视觉区域更大
            };

            /**
             * 计算控制点位置
             * @param {Object} tag 标签对象
             * @param {boolean} forClickDetection 是否用于点击检测（影响位置计算方式）
             * @returns {Array} 控制点位置数组
             */
            function calculateHandlePositions(tag, forClickDetection = false) {
                const drawBounds = getImageDrawBounds(tag);
                const { size, distance, clickableSize } = HANDLE_CONFIG;
                
                if (forClickDetection) {
                    // 用于点击检测的位置计算（使用更大的可点击区域）
                    const halfClickable = clickableSize / 2;
                    return [
                        { x: drawBounds.x - distance - halfClickable, y: drawBounds.y - distance - halfClickable, type: 'nw' },
                        { x: drawBounds.x + drawBounds.width + distance - halfClickable, y: drawBounds.y - distance - halfClickable, type: 'ne' },
                        { x: drawBounds.x - distance - halfClickable, y: drawBounds.y + drawBounds.height + distance - halfClickable, type: 'sw' },
                        { x: drawBounds.x + drawBounds.width + distance - halfClickable, y: drawBounds.y + drawBounds.height + distance - halfClickable, type: 'se' }
                    ];
                } else {
                    // 用于绘制的位置计算（使用视觉大小）
                    return [
                        { x: drawBounds.x - distance - size/2, y: drawBounds.y - distance - size/2, type: 'nw' }, // 左上
                        { x: drawBounds.x + drawBounds.width + distance - size/2, y: drawBounds.y - distance - size/2, type: 'ne' }, // 右上
                        { x: drawBounds.x - distance - size/2, y: drawBounds.y + drawBounds.height + distance - size/2, type: 'sw' }, // 左下
                        { x: drawBounds.x + drawBounds.width + distance - size/2, y: drawBounds.y + drawBounds.height + distance - size/2, type: 'se' } // 右下
                    ];
                }
            }

            /**
             * 绘制标签的缩放控制点
             * @param {Object} tag 标签对象
             */
            function drawResizeHandles(tag) {
                const handles = calculateHandlePositions(tag, false);
                const { size } = HANDLE_CONFIG;
                
                handles.forEach(handle => {
                    // 检查是否为悬停状态
                    const isHovered = hoveredTag === tag && hoveredHandle === handle.type;
                    
                    // 添加阴影效果
                    ctx.shadowColor = 'rgba(0, 0, 0, 0.3)';
                    ctx.shadowBlur = isHovered ? 6 : 4;
                    ctx.shadowOffsetX = 2;
                    ctx.shadowOffsetY = 2;
                    
                    // 绘制控制点背景
                    ctx.fillStyle = isHovered ? '#f0f9ff' : '#ffffff';
                    ctx.fillRect(handle.x, handle.y, size, size);
                    
                    // 重置阴影
                    ctx.shadowColor = 'transparent';
                    ctx.shadowBlur = 0;
                    ctx.shadowOffsetX = 0;
                    ctx.shadowOffsetY = 0;
                    
                    // 绘制控制点边框
                    ctx.strokeStyle = isHovered ? '#0ea5e9' : '#89dceb';
                    ctx.lineWidth = isHovered ? 3 : 2;
                    ctx.strokeRect(handle.x, handle.y, size, size);
                    
                    // 添加内部小圆点作为视觉提示
                    ctx.fillStyle = isHovered ? '#0ea5e9' : '#89dceb';
                    ctx.beginPath();
                    ctx.arc(handle.x + size/2, handle.y + size/2, isHovered ? 3 : 2, 0, 2 * Math.PI);
                    ctx.fill();
                });
            }
            
            /**
             * 计算绘制项目的边界框
             */
            function getDrawItemBounds(drawItem) {
                if (!drawItem.path || drawItem.path.length === 0) {
                    return { x: 0, y: 0, width: 0, height: 0 };
                }
                
                const xs = drawItem.path.map(p => p.x);
                const ys = drawItem.path.map(p => p.y);
                const minX = Math.min(...xs);
                const maxX = Math.max(...xs);
                const minY = Math.min(...ys);
                const maxY = Math.max(...ys);
                
                return {
                    x: minX,
                    y: minY,
                    width: maxX - minX,
                    height: maxY - minY
                };
            }
            

            
            /**
             * 检测鼠标是否在缩放控制点上
             * @param {number} mouseX 鼠标X坐标
             * @param {number} mouseY 鼠标Y坐标
             * @param {Object} tag 标签对象
             * @returns {string|null} 返回控制点类型或null
             */
            function getResizeHandle(mouseX, mouseY, tag) {
                if (!isEditMode) return null;
                
                const handles = calculateHandlePositions(tag, true);
                const { clickableSize } = HANDLE_CONFIG;
                
                for (let handle of handles) {
                    if (mouseX >= handle.x && mouseX <= handle.x + clickableSize &&
                        mouseY >= handle.y && mouseY <= handle.y + clickableSize) {
                        return handle.type;
                    }
                }
                
                return null;
            }
            
            /**
             * 绘制文字标签的缩放控制点
             */

            
            /**
             * 执行帧抓取和上传
             */
            async function performFrameCapture() {
                if (!video.videoWidth || video.paused || video.ended) {
                    console.log('📸 跳过帧抓取: 视频未播放或已结束');
                    return;
                }
                
                try {
                    captureCount++;
                    console.log(`📸 开始第${captureCount}次帧抓取...`);
                    
                    // 抓取当前帧
                    const frameBlob = await captureFrame();
                    console.log(`📸 帧抓取成功，大小: ${(frameBlob.size / 1024).toFixed(2)}KB`);
                    
                    // 上传到服务器
                    const uploadResult = await uploadFrame(frameBlob);
                    console.log('📤 上传成功，服务器响应:', uploadResult);
                    
                    // 更新状态显示
                    captureStatus.textContent = `帧抓取: 已完成${captureCount}次 (最近: ${new Date().toLocaleTimeString()})`;
                    
                } catch (error) {
                    console.error('❌ 帧抓取失败:', error);
                    captureStatus.textContent = `帧抓取: 错误 - ${error.message}`;
                }
            }
            
            // 绘制视频帧和图片标签
            function drawFrame(timestamp) {
                if (!lastTimestamp) lastTimestamp = timestamp;
                frameCount++;
                
                // 计算FPS（每秒更新一次）
                if (timestamp >= lastTimestamp + 1000) {
                    fps = Math.round(frameCount * 1000 / (timestamp - lastTimestamp));
                    fpsDisplay.textContent = `${fps} FPS`;
                    frameCount = 0;
                    lastTimestamp = timestamp;
                }
                
                // 清除Canvas
                ctx.clearRect(0, 0, canvas.width, canvas.height);
                
                // 绘制当前视频帧
                ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
                
                // 绘制所有标签
                tags.forEach(tag => {
                    if (!tag.loaded || !tag.image.complete) return;
                    
                    // 如果还没有设置初始位置，设置为右下角
                    if (tag.x === 0 && tag.y === 0) {
                        const padding = 20;
                        tag.x = canvas.width - tag.width - padding;
                        tag.y = canvas.height - tag.height - padding;
                    }
                    
                    // 确保标签不会超出画布边界
                    tag.x = Math.max(0, Math.min(tag.x, canvas.width - tag.width));
                    tag.y = Math.max(0, Math.min(tag.y, canvas.height - tag.height));
                    
                    // 如果是被拖动的标签，添加高亮边框
                    if (isDragging && draggedTag && draggedTag.id === tag.id) {
                        ctx.strokeStyle = '#89dceb';
                        ctx.lineWidth = 3;
                        ctx.strokeRect(tag.x - 2, tag.y - 2, tag.width + 4, tag.height + 4);
                        
                        // 添加发光效果
                        ctx.shadowColor = '#89dceb';
                        ctx.shadowBlur = 10;
                        ctx.shadowOffsetX = 0;
                        ctx.shadowOffsetY = 0;
                    }
                    
                    // 按比例绘制标签图片（保持不变形，容器尺寸不变）
                    const imgW = tag.image.naturalWidth || tag.image.width || 1;
                    const imgH = tag.image.naturalHeight || tag.image.height || 1;
                    const boxW = tag.width;
                    const boxH = tag.height;
                    const imgRatio = imgW / imgH;
                    const boxRatio = boxW / boxH;

                    let drawW, drawH;
                    if (imgRatio > boxRatio) {
                        // 图片更宽，宽度铺满，按比例缩放高度
                        drawW = boxW;
                        drawH = Math.round(boxW / imgRatio);
                    } else {
                        // 图片更高，高度铺满，按比例缩放宽度
                        drawH = boxH;
                        drawW = Math.round(boxH * imgRatio);
                    }
                    const offsetX = Math.round(tag.x + (boxW - drawW) / 2);
                    const offsetY = Math.round(tag.y + (boxH - drawH) / 2);

                    // 应用动画效果
                    let animationAlpha = 1.0;
                    let animationScale = 1.0;
                    let animationOffsetX = 0;
                    let animationOffsetY = 0;
                    
                    if (tag.animationType !== 'none' && tag.animationStartTime > 0) {
                        const elapsed = timestamp - tag.animationStartTime;
                        const animationDuration = 2000; // 2秒一个完整周期
                        const progress = (elapsed % animationDuration) / animationDuration;
                        
                        if (tag.animationType === 'blink') {
                            // 闪烁动画：透明度在10%-80%之间循环
                            const minAlpha = 0.3;
                            const maxAlpha = 0.8;
                            animationAlpha = minAlpha + (maxAlpha - minAlpha) * (0.5 + 0.5 * Math.sin(progress * Math.PI * 2));
                        } else if (tag.animationType === 'scale') {
                            // 缩放动画：大小在1.0x-1.5x之间循环
                            const minScale = 1.0;
                            const maxScale = 1.5;
                            animationScale = minScale + (maxScale - minScale) * (0.5 + 0.5 * Math.sin(progress * Math.PI * 2));
                            
                            // 计算缩放偏移，使图片从中心缩放
                            const scaledW = drawW * animationScale;
                            const scaledH = drawH * animationScale;
                            animationOffsetX = (drawW - scaledW) / 2;
                            animationOffsetY = (drawH - scaledH) / 2;
                        }
                    }
                    
                    // 保存当前绘图状态
                    ctx.save();
                    
                    // 应用透明度
                    ctx.globalAlpha = animationAlpha;
                    
                    // 绘制标签图片（应用动画效果）
                    if (tag.animationType === 'scale' && animationScale !== 1.0) {
                        const scaledW = drawW * animationScale;
                        const scaledH = drawH * animationScale;
                        ctx.drawImage(tag.image, 
                            offsetX + animationOffsetX, 
                            offsetY + animationOffsetY, 
                            scaledW, 
                            scaledH);
                    } else {
                        ctx.drawImage(tag.image, offsetX, offsetY, drawW, drawH);
                    }
                    
                    // 恢复绘图状态
                    ctx.restore();
                    
                    // 重置阴影效果
                    ctx.shadowColor = 'transparent';
                    ctx.shadowBlur = 0;
                    
                    // 在编辑模式下绘制缩放控制点
                    if (isEditMode) {
                        drawResizeHandles(tag);
                    }

                });
                
                // 绘制所有文字标签
                textTags.forEach(textTag => {
                    // 设置字体以便测量文字尺寸
                    ctx.font = `${textTag.fontSize}px Arial`;
                    
                    // 动态计算文字尺寸
                    const textMetrics = ctx.measureText(textTag.text);
                    const textWidth = textMetrics.width;
                    
                    // 获取更精确的文字高度信息
                    const actualAscent = textMetrics.actualBoundingBoxAscent || textTag.fontSize * 0.8;
                    const actualDescent = textMetrics.actualBoundingBoxDescent || textTag.fontSize * 0.2;
                    const textHeight = actualAscent + actualDescent;
                    
                    // 更新文字标签的尺寸（用于碰撞检测）
                    textTag.width = textWidth;
                    textTag.height = textHeight;
                    
                    // 如果还没有设置初始位置，设置为左上角
                    if (textTag.x === 0 && textTag.y === 0) {
                        const padding = 20;
                        textTag.x = padding;
                        textTag.y = padding + actualAscent;
                    }
                    
                    // 确保文字标签不会超出画布边界
                    textTag.x = Math.max(0, Math.min(textTag.x, canvas.width - textWidth));
                    textTag.y = Math.max(actualAscent, Math.min(textTag.y, canvas.height));
                    
                    // 计算背景区域的padding
                    const bgPadding = 6;
                    const bgX = textTag.x - bgPadding;
                    const bgY = textTag.y - actualAscent - bgPadding;
                    const bgWidth = textWidth + (bgPadding * 2);
                    const bgHeight = textHeight + (bgPadding * 2);
                    
                    // 如果是被拖动的文字标签，添加高亮边框
                    if (isDragging && draggedTextTag && draggedTextTag.id === textTag.id) {
                        ctx.strokeStyle = '#f9e2af';
                        ctx.lineWidth = 2;
                        ctx.strokeRect(bgX - 2, bgY - 2, bgWidth + 4, bgHeight + 4);
                        
                        // 添加发光效果
                        ctx.shadowColor = '#f9e2af';
                        ctx.shadowBlur = 8;
                        ctx.shadowOffsetX = 0;
                        ctx.shadowOffsetY = 0;
                    }
                    
                    // 绘制文字背景（半透明，紧贴文字）
                    if (textTag.backgroundColor && textTag.backgroundColor !== 'transparent') {
                        ctx.fillStyle = textTag.backgroundColor;
                        ctx.fillRect(bgX, bgY, bgWidth, bgHeight);
                    }
                    
                    // 绘制文字
                    ctx.fillStyle = textTag.fontColor;
                    ctx.fillText(textTag.text, textTag.x, textTag.y);
                    
                    // 重置阴影效果
                    ctx.shadowColor = 'transparent';
                    ctx.shadowBlur = 0;
                });
                
                // 绘制所有绘制项目
                drawAllDrawItems();
                
                // 继续动画循环
                // 检查是否有需要动画的标签
                const hasAnimatedTags = tags.some(tag => tag.animationType !== 'none');
                
                // 如果视频正在播放，或者正在拖动/缩放标签，或者有动画标签，或者正在绘制，都需要继续重绘
                if ((!video.paused && !video.ended) || isDragging || isResizing || hasAnimatedTags || (drawMode && isDrawing)) {
                    animationFrameId = requestAnimationFrame(drawFrame);
                }
            }
            
            // 开始绘制循环
            function startDrawing() {
                if (animationFrameId) {
                    cancelAnimationFrame(animationFrameId);
                }
                animationFrameId = requestAnimationFrame(drawFrame);
            }
            
            /**
             * 检测视频流协议类型
             * @param {string} url - 视频流URL
             * @param {string} manualType - 手动选择的协议类型
             * @returns {string} - 检测到的协议类型
             */
            function detectProtocol(url, manualType = 'auto') {
                if (manualType !== 'auto') {
                    return manualType;
                }
                
                // 自动检测协议
                if (url.includes('.m3u8')) {
                    return 'hls';
                } else if (url.includes('.flv') || url.includes('flv=1')) {
                    return 'flv';
                } else if (url.startsWith('rtmp://') || url.startsWith('rtmps://')) {
                    return 'rtmp';
                } else if (url.includes('.mp4') || url.includes('.webm')) {
                    return 'native';
                }
                
                // 默认尝试HLS
                return 'hls';
            }
            
            /**
             * 清理所有播放器实例
             */
            function cleanupPlayers() {
                // 清理HLS播放器
                if (playerInstances.hls) {
                    playerInstances.hls.destroy();
                    playerInstances.hls = null;
                }
                
                // 清理FLV播放器
                if (playerInstances.flv) {
                    playerInstances.flv.destroy();
                    playerInstances.flv = null;
                }
                
                // 清理Video.js播放器
                if (playerInstances.video) {
                    playerInstances.video.dispose();
                    playerInstances.video = null;
                }
                
                // 重置video元素
                video.src = '';
                video.load();
            }
            
            /**
             * 初始化HLS播放器
             */
            function initHLSPlayer() {
                if (Hls.isSupported()) {
                    playerInstances.hls = new Hls();
                    playerInstances.hls.loadSource(videoUrl);
                    playerInstances.hls.attachMedia(video);
                    
                    playerInstances.hls.on(Hls.Events.MANIFEST_PARSED, async function() {
                        videoStatus.textContent = '已加载';
                        playPauseBtn.disabled = false;
                        playPauseBtn.style.background = 'linear-gradient(to right, #74c7ec, #89dceb)';
                        
                        // 更新状态显示
                        currentProtocol.textContent = 'HLS';
                        currentPlayer.textContent = 'HLS.js';
                        
                        // 自动播放视频
                        try {
                            await video.play();
                            videoStatus.textContent = '播放中';
                            startDrawing();
                        } catch (error) {
                            console.error('自动播放失败:', error);
                            videoStatus.textContent = '自动播放失败，请手动播放';
                        }
                    });
                    
                    playerInstances.hls.on(Hls.Events.ERROR, function(event, data) {
                        console.error('HLS error:', data);
                        if (data.fatal) {
                            videoStatus.textContent = '错误: ' + data.type;
                        }
                    });
                } else if (video.canPlayType('application/vnd.apple.mpegurl')) {
                    // Safari原生支持
                    video.src = videoUrl;
                    videoStatus.textContent = '已加载';
                    playPauseBtn.disabled = false;
                    playPauseBtn.style.background = 'linear-gradient(to right, #74c7ec, #89dceb)';
                    
                    // 更新状态显示
                    currentProtocol.textContent = 'HLS';
                    currentPlayer.textContent = 'Native';
                    
                    video.addEventListener('loadeddata', async function() {
                        try {
                            await video.play();
                            videoStatus.textContent = '播放中';
                            startDrawing();
                        } catch (error) {
                            console.error('Safari自动播放失败:', error);
                            videoStatus.textContent = '自动播放失败，请手动播放';
                        }
                    });
                } else {
                    videoStatus.textContent = '浏览器不支持HLS';
                }
            }
            
            /**
             * 初始化FLV播放器
             */
            function initFLVPlayer() {
                if (flvjs.isSupported()) {
                    playerInstances.flv = flvjs.createPlayer({
                        type: 'flv',
                        url: videoUrl,
                        isLive: true
                    });
                    
                    playerInstances.flv.attachMediaElement(video);
                    playerInstances.flv.load();
                    
                    playerInstances.flv.on(flvjs.Events.LOADING_COMPLETE, async function() {
                        videoStatus.textContent = '已加载';
                        playPauseBtn.disabled = false;
                        playPauseBtn.style.background = 'linear-gradient(to right, #74c7ec, #89dceb)';
                        
                        // 更新状态显示
                        currentProtocol.textContent = 'HTTP-FLV';
                        currentPlayer.textContent = 'flv.js';
                        
                        try {
                            await video.play();
                            videoStatus.textContent = '播放中';
                            startDrawing();
                        } catch (error) {
                            console.error('FLV自动播放失败:', error);
                            videoStatus.textContent = '自动播放失败，请手动播放';
                        }
                    });
                    
                    playerInstances.flv.on(flvjs.Events.ERROR, function(errorType, errorDetail) {
                        console.error('FLV error:', errorType, errorDetail);
                        videoStatus.textContent = '错误: ' + errorType;
                    });
                } else {
                    videoStatus.textContent = '浏览器不支持HTTP-FLV';
                }
            }
            
            /**
             * 初始化RTMP播放器 (使用Video.js)
             */
            function initRTMPPlayer() {
                // 注意：现代浏览器已不支持Flash，RTMP需要转换为HLS或其他格式
                videoStatus.textContent = '现代浏览器不支持RTMP直播流，请使用HLS或HTTP-FLV';
                currentProtocol.textContent = 'RTMP';
                currentPlayer.textContent = '不支持';
            }
            
            /**
             * 统一的播放器初始化函数
             */
            function initPlayer() {
                // 清理之前的播放器
                cleanupPlayers();
                
                // 检测协议类型
                const selectedProtocol = protocolSelect.value;
                const detectedProtocol = detectProtocol(videoUrl, selectedProtocol);
                currentPlayerType = detectedProtocol;
                
                // 根据协议类型初始化对应播放器
                switch (detectedProtocol) {
                    case 'hls':
                        initHLSPlayer();
                        break;
                    case 'flv':
                        initFLVPlayer();
                        break;
                    case 'rtmp':
                        initRTMPPlayer();
                        break;
                    default:
                        // 默认尝试原生播放
                        video.src = videoUrl;
                        currentProtocol.textContent = 'Native';
                        currentPlayer.textContent = 'HTML5';
                        videoStatus.textContent = '已加载';
                        playPauseBtn.disabled = false;
                }
            }
            

            
            // 事件监听
            // 编辑模式切换按钮事件监听器
            editModeBtn.addEventListener('click', function() {
                isEditMode = !isEditMode;
                if (isEditMode) {
                    editModeBtn.textContent = '🔒 停止缩放';
                    editModeBtn.style.background = 'linear-gradient(135deg, #f38ba8, #eba0ac)';
                    console.log('🔍 缩放模式已开启 - 现在可以缩放图片标签');
                } else {
                    editModeBtn.textContent = '🔍 缩放图片';
                    editModeBtn.style.background = 'linear-gradient(135deg, #cba6f7, #f5c2e7)';
                    // 退出编辑模式时重置所有编辑状态
                    isResizing = false;
                    resizeHandle = null;
                    isDragging = false;
                    draggedTag = null;
                    hoveredHandle = null;
                    hoveredTag = null;
                    canvas.style.cursor = 'default';
                    console.log('🔒 编辑模式已关闭 - 标签已锁定，无法拖动或缩放');
                }
                
                // 重绘画布以显示/隐藏缩放控制点
                if (video.paused || video.ended) {
                    drawFrame();
                }
            });
            
            // 播放/暂停切换按钮事件监听器
            playPauseBtn.addEventListener('click', async function() {
                if (video.paused) {
                    // 当前是暂停状态，点击播放
                    try {
                        // 如果是第一次播放，开始绘制
                        if (video.currentTime === 0) {
                            startDrawing();
                        }
                        video.play();
                        videoStatus.textContent = '播放中';
                        playPauseBtn.innerHTML = '⏸️ 暂停视频';
                        // 切换到播放状态的样式
                        playPauseBtn.style.background = 'linear-gradient(135deg, #f38ba8, #eba0ac)';
                    } catch (error) {
                        console.error('播放失败:', error);
                        videoStatus.textContent = '播放失败';
                    }
                } else {
                    // 当前是播放状态，点击暂停
                    video.pause();
                    videoStatus.textContent = '已暂停';
                    playPauseBtn.innerHTML = '▶️ 播放视频';
                    // 切换到暂停状态的样式
                    playPauseBtn.style.background = 'linear-gradient(135deg, #cba6f7, #f5c2e7)';
                }
            });
            
            video.addEventListener('play', function() {
                console.log('🎬 视频开始播放');
                updateCanvasSize();
                startDrawing();
                playPauseBtn.innerHTML = '⏸️ 暂停视频';
                playPauseBtn.style.background = 'linear-gradient(to right, #f38ba8, #eba0ac)';
                videoStatus.textContent = '播放中';
            });
            
            video.addEventListener('pause', function() {
                playPauseBtn.innerHTML = '▶️ 播放视频';
                playPauseBtn.style.background = 'linear-gradient(to right, #74c7ec, #89dceb)';
                videoStatus.textContent = '已暂停';
            });
            
            video.addEventListener('resize', updateCanvasSize);
            

            
            // 帧抓取按钮事件
            frameCaptureBtn.addEventListener('click', function() {
                if (!isCapturing) {
                    startFrameCapture();
                } else {
                    stopFrameCapture();
                }
            });
            
            /**
             * 开始帧抓取
             */
            function startFrameCapture() {
                if (!video.videoWidth || video.paused || video.ended) {
                    console.warn('视频未准备好，跳过自动抓帧启动');
                    return;
                }
                
                isCapturing = true;
                captureCount = 0;
                
                // 获取用户设置的间隔值
                const intervalSeconds = parseInt(captureIntervalInput.value) || 3;
                const intervalMs = intervalSeconds * 1000;
                
                // 更新按钮状态
                frameCaptureBtn.textContent = '⏹️ 停止抓帧';
                frameCaptureBtn.style.background = 'linear-gradient(to right, #f38ba8, #eba0ac)';
                captureStatus.textContent = `帧抓取: 运行中 (间隔${intervalSeconds}秒)...`;
                
                console.log(`🎬 开始每${intervalSeconds}秒抓取视频帧并上传`);
                
                // 立即执行一次
                performFrameCapture();
                
                // 设置定时器，根据用户设置的间隔执行
                captureInterval = setInterval(() => {
                    performFrameCapture();
                }, intervalMs);
            }
            
            /**
             * 停止帧抓取
             */
            function stopFrameCapture() {
                isCapturing = false;
                
                // 清除定时器
                if (captureInterval) {
                    clearInterval(captureInterval);
                    captureInterval = null;
                }
                
                // 更新按钮状态
                frameCaptureBtn.textContent = '📸 开始抓帧';
                frameCaptureBtn.style.background = 'linear-gradient(to right, #74c7ec, #89dceb)';
                captureStatus.textContent = `帧抓取: 已停止 (共完成${captureCount}次)`;
                
                console.log(`🛑 帧抓取已停止，共完成${captureCount}次抓取`);
            }
             
            // 更新视频流按钮事件监听器
            updateVideoBtn.addEventListener('click', function() {
                const newVideoUrl = videoUrlInput.value.trim();
                if (!newVideoUrl) {
                    alert('请输入有效的视频流地址！');
                    return;
                }
                
                // 基本URL格式验证
                if (!newVideoUrl.startsWith('http') && !newVideoUrl.startsWith('rtmp')) {
                    alert('请输入有效的视频流地址（支持HTTP/HTTPS/RTMP协议）！');
                    return;
                }
                
                // 更新视频流地址
                videoUrl = newVideoUrl;
                
                // 停止当前播放
                if (!video.paused) {
                    video.pause();
                }
                
                // 重新初始化播放器
                videoStatus.textContent = '正在加载新视频流...';
                playPauseBtn.disabled = true;
                playPauseBtn.innerHTML = '▶️ 播放视频';
                playPauseBtn.style.background = 'linear-gradient(135deg, #cba6f7, #f5c2e7)';
                
                // 延迟一点时间再初始化，确保之前的资源已清理
                setTimeout(() => {
                    initPlayer();
                }, 100);
            });

             
             // 添加标签按钮事件监听器
            addTagBtn.addEventListener('click', function() {
                const newTag = createTag();
                console.log(`✨ 创建新标签 #${newTag.id}`);
            });
            
            // 添加文字按钮事件监听器
            addTextBtn.addEventListener('click', function() {
                const newTextTag = createTextTag();
                console.log(`✨ 创建新文字标签 #${newTextTag.id}`);
            });
            
            // 绘制模式按钮事件监听器
            drawModeBtn.addEventListener('click', function() {
                if (drawMode) {
                    exitDrawMode();
                } else {
                    startDrawMode();
                }
            });
            
            // 绘制工具选择事件监听器
            drawToolSelect.addEventListener('change', function() {
                currentDrawTool = this.value;
                console.log('🔧 切换绘制工具:', currentDrawTool);
            });
            
            // 样式设置事件监听器
            fillColorPicker.addEventListener('change', function() {
                drawSettings.fillColor = this.value;
                console.log('🎨 更新填充色:', this.value);
            });
            
            strokeColorPicker.addEventListener('change', function() {
                drawSettings.strokeColor = this.value;
                console.log('🖊️ 更新边框色:', this.value);
            });
            
            opacitySlider.addEventListener('input', function() {
                drawSettings.opacity = parseFloat(this.value);
                opacityValue.textContent = this.value;
                console.log('🔍 更新透明度:', this.value);
            });
            
            strokeWidthSlider.addEventListener('input', function() {
                drawSettings.strokeWidth = parseInt(this.value);
                strokeWidthValue.textContent = this.value + 'px';
                console.log('📏 更新线条宽度:', this.value);
            });
             
             // 拖动功能相关函数
             
             /**
              * 获取鼠标在Canvas上的相对坐标
              */
             function getMousePos(e) {
                 const rect = canvas.getBoundingClientRect();
                 const scaleX = canvas.width / rect.width;
                 const scaleY = canvas.height / rect.height;
                 
                 return {
                     x: (e.clientX - rect.left) * scaleX,
                     y: (e.clientY - rect.top) * scaleY
                 };
             }
             
             /**
              * 获取指定位置的绘制项目
              */
             function getDrawItemAtPosition(x, y) {
                 // 从后往前遍历，优先选择最上层的绘制项目
                 for (let i = drawItems.length - 1; i >= 0; i--) {
                     const drawItem = drawItems[i];
                     
                     // 检查点是否在绘制路径内
                     if (isPointInDrawPath(x, y, drawItem.path)) {
                         return drawItem;
                     }
                 }
                 return null;
             }
             
             /**
              * 检查点是否在绘制路径内
              */
             function isPointInDrawPath(x, y, path) {
                 if (path.length < 3) return false;
                 
                 // 使用射线法检测点是否在多边形内
                 let inside = false;
                 for (let i = 0, j = path.length - 1; i < path.length; j = i++) {
                     if (((path[i].y > y) !== (path[j].y > y)) &&
                         (x < (path[j].x - path[i].x) * (y - path[i].y) / (path[j].y - path[i].y) + path[i].x)) {
                         inside = !inside;
                     }
                 }
                 return inside;
             }
             
             /**
              * 检查鼠标是否在标签上
              */
             function getTagAtPosition(x, y) {
                // 从后往前遍历，优先选择最上层的标签
                for (let i = tags.length - 1; i >= 0; i--) {
                    const tag = tags[i];
                    if (x >= tag.x && x <= tag.x + tag.width &&
                        y >= tag.y && y <= tag.y + tag.height) {
                        return tag;
                    }
                }
                return null;
            }
            
            /**
             * 获取指定位置的文字标签
             */
            function getTextTagAtPosition(x, y) {
                // 从后往前遍历，优先选择最上层的文字标签
                for (let i = textTags.length - 1; i >= 0; i--) {
                    const textTag = textTags[i];
                    
                    // 创建临时canvas context来测量文字尺寸
                    const tempCanvas = document.createElement('canvas');
                    const tempCtx = tempCanvas.getContext('2d');
                    tempCtx.font = `${textTag.fontSize}px Arial`;
                    const textMetrics = tempCtx.measureText(textTag.text);
                    const textWidth = textMetrics.width;
                    
                    // 获取更精确的文字高度信息
                    const actualAscent = textMetrics.actualBoundingBoxAscent || textTag.fontSize * 0.8;
                    const actualDescent = textMetrics.actualBoundingBoxDescent || textTag.fontSize * 0.2;
                    const textHeight = actualAscent + actualDescent;
                    
                    // 计算背景区域（包含padding）
                    const bgPadding = 6;
                    const bgX = textTag.x - bgPadding;
                    const bgY = textTag.y - actualAscent - bgPadding;
                    const bgWidth = textWidth + (bgPadding * 2);
                    const bgHeight = textHeight + (bgPadding * 2);
                    
                    // 检查点击是否在背景区域内
                    if (x >= bgX && x <= bgX + bgWidth &&
                        y >= bgY && y <= bgY + bgHeight) {
                        return textTag;
                    }
                }
                return null;
            }
             
             // Canvas鼠标事件监听器
             canvas.addEventListener('mousedown', function(e) {
                const mousePos = getMousePos(e);
                
                // 如果处于绘制模式，根据绘制工具开始绘制
                if (drawMode) {
                    if (currentDrawTool === 'pen') {
                        // 钢笔模式：点击添加路径点
                        if (!isDrawing) {
                            isDrawing = true;
                            currentDrawPath = [{ x: mousePos.x, y: mousePos.y }];
                            console.log('🖊️ 钢笔模式开始绘制，起点:', mousePos);
                        } else {
                            // 继续添加点
                            currentDrawPath.push({ x: mousePos.x, y: mousePos.y });
                            console.log('🖊️ 钢笔模式添加点:', mousePos);
                        }
                        
                        // 启动绘制循环以显示实时绘制效果
                        if (!animationFrameId) {
                            animationFrameId = requestAnimationFrame(drawFrame);
                        }
                    } else if (currentDrawTool === 'lasso') {
                        // 套索模式：按下开始连续绘制
                        isDrawing = true;
                        currentDrawPath = [{ x: mousePos.x, y: mousePos.y }];
                        console.log('🎯 套索模式开始绘制，起点:', mousePos);
                    }
                    return;
                }
                
                const tag = getTagAtPosition(mousePos.x, mousePos.y);
                const textTag = getTextTagAtPosition(mousePos.x, mousePos.y);
                
                if (tag) {
                    // 检查是否点击在缩放控制点上
                    const handle = getResizeHandle(mousePos.x, mousePos.y, tag);
                    
                    if (handle && isEditMode) {
                        // 开始缩放操作
                        isResizing = true;
                        resizeHandle = handle;
                        draggedTag = tag;
                        resizeStartSize = { width: tag.width, height: tag.height };
                        resizeStartPos = { x: mousePos.x, y: mousePos.y };

                        
                        // 设置缩放光标
                        const cursors = {
                            'nw': 'nw-resize',
                            'ne': 'ne-resize',
                            'sw': 'sw-resize',
                            'se': 'se-resize'
                        };
                        canvas.style.cursor = cursors[handle];
                        
                        console.log(`🔧 开始缩放标签 #${tag.id}，控制点: ${handle}`);
                    } else {
                        // 标签拖动任何时候都允许
                        isDragging = true;
                        draggedTag = tag;
                        dragOffset.x = mousePos.x - tag.x;
                        dragOffset.y = mousePos.y - tag.y;
                        
                        // 设置Canvas样式为拖动状态
                        canvas.style.cursor = 'grabbing';
                        
                        console.log(`🎯 开始拖动标签 #${tag.id}`);
                    }
                    
                    // 如果视频暂停，启动绘制循环以显示效果
                    if (video.paused && !animationFrameId) {
                        animationFrameId = requestAnimationFrame(drawFrame);
                    }
                    
                    // 阻止默认行为
                    e.preventDefault();
                } else if (textTag) {
                    // 文字标签拖动任何时候都允许
                    isDragging = true;
                    draggedTextTag = textTag;
                    dragOffset.x = mousePos.x - textTag.x;
                    dragOffset.y = mousePos.y - textTag.y;
                    
                    // 设置Canvas样式为拖动状态
                    canvas.style.cursor = 'grabbing';
                    
                    console.log(`🎯 开始拖动文字标签 #${textTag.id}`);
                    
                    // 如果视频暂停，启动绘制循环以显示效果
                    if (video.paused && !animationFrameId) {
                        animationFrameId = requestAnimationFrame(drawFrame);
                    }
                    
                    // 阻止默认行为
                    e.preventDefault();
                } else if (!drawMode) {
                    // 在非绘制模式下检查是否点击了绘制项目
                    const drawItem = getDrawItemAtPosition(mousePos.x, mousePos.y);
                    if (drawItem) {
                        // 开始拖动绘制项目
                        isDraggingDrawItem = true;
                        draggedDrawItem = drawItem;
                        drawItemDragOffset = {
                            x: mousePos.x - drawItem.path[0].x,
                            y: mousePos.y - drawItem.path[0].y
                        };
                        
                        // 设置Canvas样式为拖动状态
                        canvas.style.cursor = 'grabbing';
                        
                        console.log(`🎯 开始拖动绘制项目 #${drawItem.id}`);
                        
                        // 如果视频暂停，启动绘制循环以显示效果
                        if (video.paused && !animationFrameId) {
                            animationFrameId = requestAnimationFrame(drawFrame);
                        }
                        
                        // 阻止默认行为
                        e.preventDefault();
                    }
                }
            });
             
             canvas.addEventListener('mousemove', function(e) {
                const mousePos = getMousePos(e);
                
                // 如果正在绘制，根据绘制工具添加路径点
                if (isDrawing && drawMode) {
                    if (currentDrawTool === 'lasso') {
                        // 套索模式：连续添加路径点
                        currentDrawPath.push({ x: mousePos.x, y: mousePos.y });
                        
                        // 启动绘制循环以显示实时绘制效果
                        if (!animationFrameId) {
                            animationFrameId = requestAnimationFrame(drawFrame);
                        }
                    }
                    // 钢笔模式在mousedown和click事件中处理
                    return;
                }
                
                if (isResizing && draggedTag && resizeHandle) {
                     // 缩放操作 - 添加缩放因子以提高操作平滑度
                     const scaleFactor = 0.8; // 缩放灵敏度因子，降低过于敏感的缩放
                     const deltaX = (mousePos.x - resizeStartPos.x) * scaleFactor;
                     const deltaY = (mousePos.y - resizeStartPos.y) * scaleFactor;
                     
                     // 计算原始长宽比
                     const originalAspectRatio = resizeStartSize.width / resizeStartSize.height;
                     
                     let newWidth = resizeStartSize.width;
                     let newHeight = resizeStartSize.height;
                     let newX = draggedTag.x;
                     let newY = draggedTag.y;
                     
                     // 等比缩放：固定对应角点，根据鼠标移动距离计算缩放比例
                     let scaleRatio = 1;
                     let fixedCornerX, fixedCornerY; // 固定的角点坐标
                     
                     // 根据控制点确定固定的角点
                     switch (resizeHandle) {
                         case 'nw': // 左上角控制点，固定右下角
                             fixedCornerX = draggedTag.x + draggedTag.width;
                             fixedCornerY = draggedTag.y + draggedTag.height;
                             break;
                         case 'ne': // 右上角控制点，固定左下角
                             fixedCornerX = draggedTag.x;
                             fixedCornerY = draggedTag.y + draggedTag.height;
                             break;
                         case 'sw': // 左下角控制点，固定右上角
                             fixedCornerX = draggedTag.x + draggedTag.width;
                             fixedCornerY = draggedTag.y;
                             break;
                         case 'se': // 右下角控制点，固定左上角
                             fixedCornerX = draggedTag.x;
                             fixedCornerY = draggedTag.y;
                             break;
                     }
                     
                     // 计算当前鼠标到固定角点的距离
                     const currentDistance = Math.sqrt(
                         Math.pow(mousePos.x - fixedCornerX, 2) + 
                         Math.pow(mousePos.y - fixedCornerY, 2)
                     );
                     
                     // 计算初始鼠标到固定角点的距离
                     const initialDistance = Math.sqrt(
                         Math.pow(resizeStartPos.x - fixedCornerX, 2) + 
                         Math.pow(resizeStartPos.y - fixedCornerY, 2)
                     );
                     
                     // 计算缩放比例
                     if (initialDistance > 0) {
                         scaleRatio = currentDistance / initialDistance;
                     }
                     
                     // 应用等比缩放
                     newWidth = resizeStartSize.width * scaleRatio;
                     newHeight = resizeStartSize.height * scaleRatio;
                     
                     // 根据固定角点和新尺寸计算新位置
                     switch (resizeHandle) {
                         case 'nw': // 左上角控制点，固定右下角
                             newX = fixedCornerX - newWidth;
                             newY = fixedCornerY - newHeight;
                             break;
                         case 'ne': // 右上角控制点，固定左下角
                             newX = fixedCornerX;
                             newY = fixedCornerY - newHeight;
                             break;
                         case 'sw': // 左下角控制点，固定右上角
                             newX = fixedCornerX - newWidth;
                             newY = fixedCornerY;
                             break;
                         case 'se': // 右下角控制点，固定左上角
                             newX = fixedCornerX;
                             newY = fixedCornerY;
                             break;
                     }
                     
                     // 限制最小尺寸和变化阈值
                     const minSize = 20;
                     const changeThreshold = 2; // 最小变化阈值，避免微小移动
                     
                     // 检查是否有足够的变化值得更新
                     const widthChange = Math.abs(newWidth - draggedTag.width);
                     const heightChange = Math.abs(newHeight - draggedTag.height);
                     const posXChange = Math.abs(newX - draggedTag.x);
                     const posYChange = Math.abs(newY - draggedTag.y);
                     
                     if ((widthChange >= changeThreshold || heightChange >= changeThreshold || 
                          posXChange >= changeThreshold || posYChange >= changeThreshold) &&
                         newWidth >= minSize && newHeight >= minSize) {
                         // 确保不会超出画布边界
                         if (newX >= 0 && newX + newWidth <= canvas.width &&
                             newY >= 0 && newY + newHeight <= canvas.height) {
                             draggedTag.width = Math.round(newWidth);
                             draggedTag.height = Math.round(newHeight);
                             draggedTag.x = Math.round(newX);
                             draggedTag.y = Math.round(newY);
                         }
                     }
                     
                     e.preventDefault();
                 } else if (isDragging && draggedTag) {
                     // 拖动操作
                     draggedTag.x = mousePos.x - dragOffset.x;
                     draggedTag.y = mousePos.y - dragOffset.y;
                     
                     // 确保标签不会超出画布边界
                     draggedTag.x = Math.max(0, Math.min(draggedTag.x, canvas.width - draggedTag.width));
                     draggedTag.y = Math.max(0, Math.min(draggedTag.y, canvas.height - draggedTag.height));
                     
                     // 实时更新位置显示
                     updateTagPositionDisplay(draggedTag);
                     
                     e.preventDefault();
                 } else if (isDragging && draggedTextTag) {
                    // 文字标签拖动操作
                    draggedTextTag.x = mousePos.x - dragOffset.x;
                    draggedTextTag.y = mousePos.y - dragOffset.y;
                    
                    // 动态计算文字尺寸用于边界检查
                    const tempCanvas = document.createElement('canvas');
                    const tempCtx = tempCanvas.getContext('2d');
                    tempCtx.font = `${draggedTextTag.fontSize}px Arial`;
                    const textMetrics = tempCtx.measureText(draggedTextTag.text);
                    const textWidth = textMetrics.width;
                    
                    // 获取更精确的文字高度信息
                    const actualAscent = textMetrics.actualBoundingBoxAscent || draggedTextTag.fontSize * 0.8;
                    const actualDescent = textMetrics.actualBoundingBoxDescent || draggedTextTag.fontSize * 0.2;
                    const textHeight = actualAscent + actualDescent;
                    
                    // 确保标签不会超出画布边界（考虑背景padding）
                    const bgPadding = 6;
                    draggedTextTag.x = Math.max(bgPadding, Math.min(draggedTextTag.x, canvas.width - textWidth - bgPadding));
                    draggedTextTag.y = Math.max(actualAscent + bgPadding, Math.min(draggedTextTag.y, canvas.height - actualDescent - bgPadding));
                     
                     // 实时更新位置显示
                     updateTextTagPositionDisplay(draggedTextTag);
                     
                     e.preventDefault();
                 } else if (isDraggingDrawItem && draggedDrawItem) {
                     // 绘制项目拖动操作
                     const deltaX = mousePos.x - drawItemDragOffset.x - draggedDrawItem.path[0].x;
                     const deltaY = mousePos.y - drawItemDragOffset.y - draggedDrawItem.path[0].y;
                     
                     // 移动整个路径
                     for (let point of draggedDrawItem.path) {
                         point.x += deltaX;
                         point.y += deltaY;
                     }
                     
                     // 确保绘制项目不会超出画布边界
                     let minX = Math.min(...draggedDrawItem.path.map(p => p.x));
                     let maxX = Math.max(...draggedDrawItem.path.map(p => p.x));
                     let minY = Math.min(...draggedDrawItem.path.map(p => p.y));
                     let maxY = Math.max(...draggedDrawItem.path.map(p => p.y));
                     
                     if (minX < 0 || maxX > canvas.width || minY < 0 || maxY > canvas.height) {
                         // 如果超出边界，撤销移动
                         for (let point of draggedDrawItem.path) {
                             point.x -= deltaX;
                             point.y -= deltaY;
                         }
                     }
                     
                     console.log(`🎯 拖动绘制项目 #${draggedDrawItem.id}，偏移: (${deltaX}, ${deltaY})`);
                     
                     e.preventDefault();
                 } else {
                     // 检查鼠标悬停状态，更新鼠标样式和悬停高亮
                     const tag = getTagAtPosition(mousePos.x, mousePos.y);
                     const textTag = getTextTagAtPosition(mousePos.x, mousePos.y);
                     const drawItem = getDrawItemAtPosition(mousePos.x, mousePos.y);
                     let newHoveredHandle = null;
                     let newHoveredTag = null;

                     
                     if (tag) {
                         // 检查是否在缩放模式下悬停在缩放控制点上
                         if (isEditMode) {
                             const handle = getResizeHandle(mousePos.x, mousePos.y, tag);
                             if (handle) {
                                 newHoveredHandle = handle;
                                 newHoveredTag = tag;
                                 const cursors = {
                                     'nw': 'nw-resize',
                                     'ne': 'ne-resize',
                                     'sw': 'sw-resize',
                                     'se': 'se-resize'
                                 };
                                 canvas.style.cursor = cursors[handle];
                             } else {
                                 canvas.style.cursor = 'grab';
                             }
                         } else {
                             // 非缩放模式下，标签始终显示可拖动光标
                             canvas.style.cursor = 'grab';
                         }
                     } else if (textTag) {
                         // 文字标签任何时候都可以拖动
                         canvas.style.cursor = 'grab';
                     } else if (drawItem && !drawMode) {
                         // 绘制项目在非绘制模式下可以拖动
                         canvas.style.cursor = 'grab';
                     } else {
                         canvas.style.cursor = 'default';
                     }
                     
                     // 更新悬停状态，如果有变化则重绘
                     if (hoveredHandle !== newHoveredHandle || hoveredTag !== newHoveredTag) {
                         hoveredHandle = newHoveredHandle;
                         hoveredTag = newHoveredTag;
                         
                         // 如果视频暂停，触发重绘以显示悬停效果
                         if (video.paused && !animationFrameId) {
                             animationFrameId = requestAnimationFrame(drawFrame);
                         }
                     }
                 }
             });
             
             canvas.addEventListener('mouseup', function(e) {
                // 如果正在绘制，根据绘制工具处理结束逻辑
                if (isDrawing && drawMode) {
                    if (currentDrawTool === 'lasso') {
                        // 套索模式：松开鼠标结束绘制
                        isDrawing = false;
                    } else if (currentDrawTool === 'pen') {
                        // 钢笔模式：不在mouseup时结束，需要双击或右键结束
                        return;
                    }
                    
                    // 检查路径是否闭合
                    if (isPathClosed(currentDrawPath)) {
                        // 创建新的绘制项目
                        const drawItem = {
                            id: ++drawItemIdCounter,
                            path: [...currentDrawPath],
                            fillColor: drawSettings.fillColor,
                            strokeColor: drawSettings.strokeColor,
                            opacity: drawSettings.opacity,
                            strokeWidth: drawSettings.strokeWidth,
                            tool: currentDrawTool,
                            closed: true
                        };
                        
                        drawItems.push(drawItem);
                        renderDrawItem(drawItem);
                        
                        console.log('✅ 绘制完成并闭合，创建绘制项目:', drawItem);
                    } else {
                        console.log('⚠️ 绘制未闭合，路径被丢弃');
                    }
                    
                    // 清空当前路径
                    currentDrawPath = [];
                    return;
                }
                
                if (isResizing && draggedTag) {
                     console.log(`✅ 标签 #${draggedTag.id} 缩放完成，新尺寸: ${Math.round(draggedTag.width)}x${Math.round(draggedTag.height)}`);
                     
                     isResizing = false;
                     resizeHandle = null;
                     draggedTag = null;
                     resizeStartSize = { width: 0, height: 0 };
                     resizeStartPos = { x: 0, y: 0 };
                     
                     // 恢复鼠标样式
                     canvas.style.cursor = 'default';
                     
                     // 如果视频暂停且缩放结束，停止绘制循环以节省性能
                     if (video.paused && animationFrameId) {
                         cancelAnimationFrame(animationFrameId);
                         animationFrameId = null;
                         // 最后绘制一次确保标签正确显示
                         drawFrame(performance.now());
                     }
                     
                     e.preventDefault();

                 } else if (isDragging && draggedTag) {
                     console.log(`✅ 标签 #${draggedTag.id} 拖动完成，新位置: (${Math.round(draggedTag.x)}, ${Math.round(draggedTag.y)})`);
                     
                     isDragging = false;
                     draggedTag = null;
                     dragOffset = { x: 0, y: 0 };
                     
                     // 恢复鼠标样式
                     canvas.style.cursor = 'default';
                     
                     // 如果视频暂停且拖动结束，停止绘制循环以节省性能
                     if (video.paused && animationFrameId) {
                         cancelAnimationFrame(animationFrameId);
                         animationFrameId = null;
                         // 最后绘制一次确保标签位置正确显示
                         drawFrame(performance.now());
                     }
                     
                     e.preventDefault();
                 } else if (isDragging && draggedTextTag) {
                     console.log(`✅ 文字标签 #${draggedTextTag.id} 拖动完成，新位置: (${Math.round(draggedTextTag.x)}, ${Math.round(draggedTextTag.y)})`);
                     
                     isDragging = false;
                     draggedTextTag = null;
                     dragOffset = { x: 0, y: 0 };
                     
                     // 恢复鼠标样式
                     canvas.style.cursor = 'default';
                     
                     // 如果视频暂停且拖动结束，停止绘制循环以节省性能
                     if (video.paused && animationFrameId) {
                         cancelAnimationFrame(animationFrameId);
                         animationFrameId = null;
                         // 最后绘制一次确保标签位置正确显示
                         drawFrame(performance.now());
                     }
                     
                     e.preventDefault();
                 } else if (isDraggingDrawItem && draggedDrawItem) {
                     console.log(`✅ 绘制项目 #${draggedDrawItem.id} 拖动完成`);
                     
                     isDraggingDrawItem = false;
                     draggedDrawItem = null;
                     drawItemDragOffset = { x: 0, y: 0 };
                     
                     // 恢复鼠标样式
                     canvas.style.cursor = 'default';
                     
                     // 如果视频暂停且拖动结束，停止绘制循环以节省性能
                     if (video.paused && animationFrameId) {
                         cancelAnimationFrame(animationFrameId);
                         animationFrameId = null;
                         // 最后绘制一次确保绘制项目位置正确显示
                         drawFrame(performance.now());
                     }
                     
                     e.preventDefault();
                 }
             });
             
             // 双击事件监听器 - 用于结束钢笔模式绘制
             canvas.addEventListener('dblclick', function(e) {
                 if (isDrawing && drawMode && currentDrawTool === 'pen') {
                     // 钢笔模式：双击结束绘制
                     isDrawing = false;
                     
                     console.log('🖊️ 钢笔模式双击结束绘制');
                     
                     // 检查路径是否闭合
                     if (isPathClosed(currentDrawPath)) {
                         // 创建新的绘制项目
                         const drawItem = {
                             id: ++drawItemIdCounter,
                             path: [...currentDrawPath],
                             fillColor: drawSettings.fillColor,
                             strokeColor: drawSettings.strokeColor,
                             opacity: drawSettings.opacity,
                             strokeWidth: drawSettings.strokeWidth,
                             tool: currentDrawTool,
                             closed: true
                         };
                         
                         drawItems.push(drawItem);
                         renderDrawItem(drawItem);
                         
                         console.log('✅ 钢笔绘制完成并闭合，创建绘制项目:', drawItem);
                     } else {
                         console.log('⚠️ 钢笔绘制未闭合，路径被丢弃');
                     }
                     
                     // 清空当前路径
                     currentDrawPath = [];
                     e.preventDefault();
                 }
             });
             
             // 处理鼠标离开Canvas区域的情况
             canvas.addEventListener('mouseleave', function(e) {
                 // 重置悬停状态
                 if (hoveredHandle !== null || hoveredTag !== null) {
                     hoveredHandle = null;
                     hoveredTag = null;
                     
                     // 如果视频暂停，触发重绘以清除悬停效果
                     if (video.paused && !animationFrameId) {
                         animationFrameId = requestAnimationFrame(drawFrame);
                     }
                 }
                 
                 if (isResizing) {
                     isResizing = false;
                     resizeHandle = null;
                     draggedTag = null;
                     draggedTextTag = null;
                     resizeStartSize = { width: 0, height: 0 };
                     resizeStartPos = { x: 0, y: 0 };
                     canvas.style.cursor = 'default';
                     
                     // 如果视频暂停且缩放结束，停止绘制循环以节省性能
                     if (video.paused && animationFrameId) {
                         cancelAnimationFrame(animationFrameId);
                         animationFrameId = null;
                         // 最后绘制一次确保标签正确显示
                         drawFrame(performance.now());
                     }
                     
                     console.log('🚫 缩放被取消（鼠标离开Canvas区域）');
                 } else if (isDragging) {
                     isDragging = false;
                     draggedTag = null;
                     draggedTextTag = null;
                     dragOffset = { x: 0, y: 0 };
                     canvas.style.cursor = 'default';
                     
                     // 如果视频暂停且拖动结束，停止绘制循环以节省性能
                     if (video.paused && animationFrameId) {
                         cancelAnimationFrame(animationFrameId);
                         animationFrameId = null;
                         // 最后绘制一次确保标签位置正确显示
                         drawFrame(performance.now());
                     }
                     
                     console.log('🚫 拖动被取消（鼠标离开Canvas区域）');
                 }
             });
             
             /**
             * 初始化图片combobox功能
             */
            function initImageComboboxes() {
                // 为每个图片combobox添加事件监听器
                document.addEventListener('click', function(e) {
                    // 处理图片combobox下拉按钮点击
                    if (e.target.classList.contains('image-combobox-btn')) {
                        e.preventDefault();
                        e.stopPropagation();
                        
                        const tagId = e.target.getAttribute('data-tag-id');
                        const dropdown = document.querySelector(`.image-combobox-dropdown[data-tag-id="${tagId}"]`);
                        
                        if (dropdown) {
                            // 关闭其他所有下拉列表
                            document.querySelectorAll('.image-combobox-dropdown').forEach(d => {
                                if (d !== dropdown) {
                                    d.classList.remove('show');
                                }
                            });
                            
                            // 切换当前下拉列表
                            dropdown.classList.toggle('show');
                            
                            // 更新按钮文本
                            if (dropdown.classList.contains('show')) {
                                e.target.textContent = '▲';
                            } else {
                                e.target.textContent = '▼';
                            }
                        }
                    }
                    
                    // 处理图片combobox选项点击
                    if (e.target.classList.contains('combobox-option') && e.target.closest('.image-combobox-dropdown')) {
                        const dropdown = e.target.closest('.image-combobox-dropdown');
                        const tagId = dropdown.getAttribute('data-tag-id');
                        const value = e.target.getAttribute('data-value');
                        const input = document.querySelector(`.tag-url-input[data-tag-id="${tagId}"]`);
                        const btn = document.querySelector(`.image-combobox-btn[data-tag-id="${tagId}"]`);
                        
                        if (input && btn) {
                            // 更新输入框值
                            input.value = value;
                            
                            // 触发输入框的change事件来更新标签
                            const changeEvent = new Event('input', { bubbles: true });
                            input.dispatchEvent(changeEvent);
                            
                            // 关闭下拉列表
                            dropdown.classList.remove('show');
                            btn.textContent = '▼';
                            
                            console.log(`✅ 图片标签 #${tagId} 地址更新为: ${value}`);
                        }
                    }
                    
                    // 点击外部关闭所有图片combobox下拉列表
                    if (!e.target.closest('.custom-combobox')) {
                        document.querySelectorAll('.image-combobox-dropdown').forEach(dropdown => {
                            dropdown.classList.remove('show');
                        });
                        document.querySelectorAll('.image-combobox-btn').forEach(btn => {
                            btn.textContent = '▼';
                        });
                    }
                });
                
                console.log('✅ 图片combobox功能已初始化');
            }
            
             // 初始化
            initPlayer();
            updateCanvasSize();
            initImageComboboxes();
            
            // 设置初始Canvas尺寸
            canvas.width = 800;
            canvas.height = 450;
            resolutionDisplay.textContent = `${canvas.width}×${canvas.height}`;
            
            // 初始化绘制功能
            console.log('🎨 绘制功能已初始化');
            console.log('📝 当前绘制工具:', currentDrawTool);
            console.log('🎨 当前绘制样式:', drawSettings);
            console.log('📋 绘制项目列表:', drawItems);
        });
    </script>
</body>
</html>
